Go language _ more types: struct, slice and mapping

More Type: struct, slice and mapping
learn how to define new types based on existing types: This lesson covers the structures, arrays, slices, and maps.

Go write authors group, Go-zh group translation.
https://tour.go-zh.org/moretypes/1

  • pointer

Go has pointers. Save the memory address pointer value.

Type *Tis a pointer Ttype value of the pointer. Its value is zero nil.

var p *int

& Operator generates a pointer to its operands.

i := 42
p = &i

* Operator indicates the bottom pointer value.

fmt.Println(*p) // 通过指针 p 读取 i
*p = 21         // 通过指针 p 设置 i

This is commonly referred to as "indirect references" or "redirect."

And C different, Go no pointer arithmetic.

// +build OMIT

package main

import "fmt"

func main() {
    i, j := 42, 2701

    p := &i         // 指向 i
    fmt.Println(*p) // 通过指针读取 i 的值
    *p = 21         // 通过指针设置 i 的值
    fmt.Println(i)  // 查看 i 的值

    p = &j         // 指向 j
    *p = *p / 37   // 通过指针对 j 进行除法运算
    fmt.Println(j) // 查看 j 的值
}
  • Structure

A structure ( struct) is a set of fields (field).

// +build OMIT

package main

import "fmt"

type Vertex struct {
    X int
    Y int
}

func main() {
    fmt.Println(Vertex{1, 2})
}
  • Structure fields

Field uses dot structures to access.

// +build OMIT

package main

import "fmt"

type Vertex struct {
    X int
    Y int
}

func main() {
    v := Vertex{1, 2}
    v.X = 4
    fmt.Println(v.X)
}
  • Structure pointer

Structure fields can be accessed by a pointer to a structure.

If we have a pointer to a structure p, you can (*p).Xaccess its fields X. But so write too long-winded, so the language also allows us to use implicit indirect reference, write directly p.Xon it.

// +build OMIT

package main

import "fmt"

type Vertex struct {
    X int
    Y int
}

func main() {
    v := Vertex{1, 2}
    p := &v
    p.X = 1e9
    fmt.Println(v)
}
  • Structure grammar

Structure grammar to assign a new value field structure by a direct listed.

Use Name:syntax to list only part of the field. (Irrespective of the order of field names.)

Special prefix &returns a pointer to structure.

// +build OMIT

package main

import "fmt"

type Vertex struct {
    X, Y int
}

var (
    v1 = Vertex{1, 2}  // 创建一个 Vertex 类型的结构体
    v2 = Vertex{X: 1}  // Y:0 被隐式地赋予
    v3 = Vertex{}      // X:0 Y:0
    p  = &Vertex{1, 2} // 创建一个 *Vertex 类型的结构体(指针)
)

func main() {
    fmt.Println(v1, p, v2, v3)
}
  • Array

The type of [n]Trepresentation has na Tarray of values of type.

expression

var a [10]int

It will be variable adeclared as an array with 10 integers.

Part of its length of the array type and therefore the size of the array can not be changed. This appears to be a limit, but that's OK, Go provides a more convenient way to use an array.

// +build OMIT

package main

import "fmt"

func main() {
    var a [2]string
    a[0] = "Hello"
    a[1] = "World"
    fmt.Println(a[0], a[1])
    fmt.Println(a)

    primes := [6]int{2, 3, 5, 7, 11, 13}
    fmt.Println(primes)
}
  • slice

The size of each array are fixed. The slice was the size of the array elements to provide dynamic, flexible viewing angle. In practice, the slice is more commonly used than arrays.

Type []Trepresents an element type Tof slice.

Slice defined by two subscripts, i.e. a lower bound and an upper bound, both separated by colons:

a[low : high]

It will choose a half-open range, including the first element, but excluding the last element.

The following expression creates a slice that contains athe index of the elements from 1-3:

a[1:4]
// +build OMIT

package main

import "fmt"

func main() {
    primes := [6]int{2, 3, 5, 7, 11, 13}

    var s []int = primes[1:4]
    fmt.Println(s)
}
  • Slice like a reference to the array

Slice does not store any data, it merely describes some of the underlying array.

Change slices modify the underlying array element corresponding elements.

Share it with the underlying array sections are observed to such modifications.

// +build OMIT

package main

import "fmt"

func main() {
    names := [4]string{
        "John",
        "Paul",
        "George",
        "Ringo",
    }
    fmt.Println(names)

    a := names[0:2]
    b := names[1:3]
    fmt.Println(a, b)

    b[0] = "XXX"
    fmt.Println(a, b)
    fmt.Println(names)
}
  • Slice grammar

Grammar Grammar no array sections similar length.

This is an array of grammar:

[3]bool{true, true, false}

Below this will create one and the same array above, and then constructed a reference to its slice:

[]bool{true, true, false}
// +build OMIT

package main

import "fmt"

func main() {
    q := []int{2, 3, 5, 7, 11, 13}
    fmt.Println(q)

    r := []bool{true, false, true, true, false, true}
    fmt.Println(r)

    s := []struct {
        i int
        b bool
    }{
        {2, true},
        {3, false},
        {5, true},
        {7, true},
        {11, false},
        {13, true},
    }
    fmt.Println(s)
}
  • The default behavior slices

During slicing, you can use it to override the default behavior of bounds.

The default value of the slice lower bound 0, the upper bound is the length of the slice.

For array

var a [10]int

, The following sections are equivalent:

a[0:10]
a[:10]
a[0:]
a[:]
// +build OMIT

package main

import "fmt"

func main() {
    s := []int{2, 3, 5, 7, 11, 13}

    s = s[1:4]
    fmt.Println(s)

    s = s[:2]
    fmt.Println(s)

    s = s[1:]
    fmt.Println(s)
}
  • Slice length and capacity

Slice has length and capacity .

The length of the slice is the number of elements it contains.

The capacity is the number of slices in the first element from its beginning to the end of the number of the underlying array element.

Slice slength and capacity by expressions len(s)and cap(s)acquired.

As long as sufficient capacity, you can extend a slice by slice again. Try to modify a slicing the sample program, making it longer than the capacity (which is about to expand beyond its capacity range), and see what happens.

// +build OMIT

package main

import "fmt"

func main() {
    s := []int{2, 3, 5, 7, 11, 13}
    printSlice(s)

    // 截取切片使其长度为 0
    s = s[:0]
    printSlice(s)

    // 拓展其长度
    s = s[:4]
    printSlice(s)

    // 舍弃前两个值
    s = s[2:]
    printSlice(s)
}

func printSlice(s []int) {
    fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}
  • nil slice

Zero value slice is nil.

nil slice length and a capacity of 0 and no underlying array.

// +build OMIT

package main

import "fmt"

func main() {
    var s []int
    fmt.Println(s, len(s), cap(s))
    if s == nil {
        fmt.Println("nil!")
    }
}
  • Create a slice with make

Slice with a built-in function can makebe created, and this is the way you create a dynamic array.

make Function allocates an array element value of zero and returns a reference to its slice:

a := make([]int, 5)  // len(a)=5

To specify its capacity, the need to makepass the third parameter:

b := make([]int, 0, 5) // len(b)=0, cap(b)=5

b = b[:cap(b)] // len(b)=5, cap(b)=5
b = b[1:]      // len(b)=4, cap(b)=4
// +build OMIT

package main

import "fmt"

func main() {
    a := make([]int, 5)
    printSlice("a", a)

    b := make([]int, 0, 5)
    printSlice("b", b)

    c := b[:2]
    printSlice("c", c)

    d := c[2:5]
    printSlice("d", d)
}

func printSlice(s string, x []int) {
    fmt.Printf("%s len=%d cap=%d %v\n",
        s, len(x), cap(x), x)
}
  • Slice slice

Slice may comprise any type, even other slices.

// +build OMIT

package main

import (
    "fmt"
    "strings"
)

func main() {
    // 创建一个井字板(经典游戏)
    board := [][]string{
        []string{"_", "_", "_"},
        []string{"_", "_", "_"},
        []string{"_", "_", "_"},
    }

    // 两个玩家轮流打上 X 和 O
    board[0][0] = "X"
    board[2][2] = "O"
    board[1][2] = "X"
    board[1][0] = "O"
    board[0][2] = "X"

    for i := 0; i < len(board); i++ {
        fmt.Printf("%s\n", strings.Join(board[i], " "))
    }
}
  • To slice an additional element

Slices add a new element is commonly used in the operation, aims to provide a built-Go appendfunction. Built-in functions [[ https://go-zh.org/pkg/builtin/#append ] [documentation]] have this function in detail.

func append(s []T, vs ...T) []T

appendThe first parameter sis a type of element Tsections, other types of Tvalues will be appended to the end of the slice.

append The result is a slice that contains all the elements of the original plus the newly added sections element.

When sthe time of the underlying array is too small to accommodate all the values given, it will be assigned a larger array. Returned slice will point to this newly allocated array.

(To learn more about slices, please read the article [[ https://blog.go-zh.org/go-slices-usage-and-internals ] [Go sections: Usage and nature]].)

// +build OMIT

package main

import "fmt"

func main() {
    var s []int
    printSlice(s)

    // 添加一个空切片
    s = append(s, 0)
    printSlice(s)

    // 这个切片会按需增长
    s = append(s, 1)
    printSlice(s)

    // 可以一次性添加多个元素
    s = append(s, 2, 3, 4)
    printSlice(s)
}

func printSlice(s []int) {
    fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}
  • Range

forLoop rangeform or map may traverse sections.

When using forthe time slicing cycle through each iteration will return two values. A copy of the first element is the current element index, the second index corresponding to the value.

// +build OMIT

package main

import "fmt"

var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}

func main() {
    for i, v := range pow {
        fmt.Printf("2**%d = %d\n", i, v)
    }
}
  • range (cont.)

Index or value may be given _to ignore it.

for i, _ := range pow
for _, value := range pow

If you only need the index, ignore the second variable.

for i := range pow
// +build OMIT

package main

import "fmt"

func main() {
    pow := make([]int, 10)
    for i := range pow {
        pow[i] = 1 << uint(i) // == 2**i
    }
    for _, value := range pow {
        fmt.Printf("%d\n", value)
    }
}
  • Exercise: Slice

Achieved Pic. It should return the length of a dyslice, wherein a length of each element dx, the element type uint8of a slice. When you run this program, it will be interpreted as grayscale each integer value (well, in fact, is the blue value) and displays the image to which it corresponds.

Select the image you to decide. Several interesting functions include (x+y)/2, x*y, x^y, x*log(y)and x%(y+1).

(Hint: use a loop to assign [][]uint8each []uint8; please use uint8(intValue)between type conversion; you might use mathfunction package.)

// +build no-build OMIT

package main

import "golang.org/x/tour/pic"

func Pic(dx, dy int) [][]uint8 {
}

func main() {
    pic.Show(Pic)
}
  • Mapping ( map)

Mapping maps keys to values.

Mapping zero value nil. nilMapping neither bond nor add key.

make Function returns the given type of mapping, and initializes its standby.

// +build OMIT

package main

import "fmt"

type Vertex struct {
    Lat, Long float64
}

var m map[string]Vertex

func main() {
    m = make(map[string]Vertex)
    m["Bell Labs"] = Vertex{
        40.68433, -74.39967,
    }
    fmt.Println(m["Bell Labs"])
}
  • Mapping of grammar

Mapping grammar and structure similar, but must have a key name.

// +build OMIT

package main

import "fmt"

type Vertex struct {
    Lat, Long float64
}

var m = map[string]Vertex{
    "Bell Labs": Vertex{
        40.68433, -74.39967,
    },
    "Google": Vertex{
        37.42202, -122.08408,
    },
}

func main() {
    fmt.Println(m)
}
  • Mapping of grammar (cont.)

If the top-level type is just a type name, you can omit it from the elements of grammar.

// +build OMIT

package main

import "fmt"

type Vertex struct {
    Lat, Long float64
}

var m = map[string]Vertex{
    "Bell Labs": {40.68433, -74.39967},
    "Google":    {37.42202, -122.08408},
}

func main() {
    fmt.Println(m)
}
  • Modifying the mapping

Mapping minserted or modified elements:

m[key] = elem

Gets the element:

elem = m[key]

Removing elements:

delete(m, key)

Whether there is a key assignment by double detection:

elem, ok = m[key]

If keyin the mmiddle, okit is true; otherwise, okis false.

If keynot in the map, then elema zero value element is the mapping type.

Similarly, when reading from a key mapping does not exist, the result is a zero value element type mapping.

Note : If you elemor okhas not been declared, you can use short variable declarations:

elem, ok := m[key]
// +build OMIT

package main

import "fmt"

func main() {
    m := make(map[string]int)

    m["Answer"] = 42
    fmt.Println("The value:", m["Answer"])

    m["Answer"] = 48
    fmt.Println("The value:", m["Answer"])

    delete(m, "Answer")
    fmt.Println("The value:", m["Answer"])

    v, ok := m["Answer"]
    fmt.Println("The value:", v, "Present?", ok)
}
  • Exercise: Mapping

Achieved WordCount. It should return a map which contains the string snumber in each "word" of. Function wc.Testwill perform a series of test cases for this function, and outputs success or failure.

You will find [[ https://go-zh.org/pkg/strings/#Fields ] [strings.Fields]] helpful.

// +build OMIT

package main

import (
    "golang.org/x/tour/wc"
)

func WordCount(s string) map[string]int {
    return map[string]int{"x": 1}
}

func main() {
    wc.Test(WordCount)
}
  • Function value

Functions are also values. Other values ​​can be passed as they are the same.

Function values ​​may be used as parameters or function return values.

// +build OMIT

package main

import (
    "fmt"
    "math"
)

func compute(fn func(float64, float64) float64) float64 {
    return fn(3, 4)
}

func main() {
    hypot := func(x, y float64) float64 {
        return math.Sqrt(x*x + y*y)
    }
    fmt.Println(hypot(5, 12))

    fmt.Println(compute(hypot))
    fmt.Println(compute(math.Pow))
}
  • Closure function

Go function may be a closure. A closure is a function value, it refers to a function of the variables outside the body. This function can access and impart its reference value variable, in other words, the function of these variables are "bound" together.

For example, the function adderreturns a closure. Each closure are bound at their respective sumupper variable.

// +build OMIT

package main

import "fmt"

func adder() func(int) int {
    sum := 0
    return func(x int) int {
        sum += x
        return sum
    }
}

func main() {
    pos, neg := adder(), adder()
    for i := 0; i < 10; i++ {
        fmt.Println(
            pos(i),
            neg(-2*i),
        )
    }
}
  • Exercise: Fibonacci closure

Let's use the function to do fun things.

Implement a fibonaccifunction that returns a function (closure), which returns a closure [[ https://zh.wikipedia.org/wiki/%E6%96%90%E6%B3%A2%E9%82%A3 91 is E5% A5%%%% 95% B0 E6 E5% 88% 97% ] (0, 1, 1, 2, 3, 5, ...)[fibonacci]] .

// +build no-build OMIT

package main

import "fmt"

// 返回一个“返回int的函数”
func fibonacci() func() int {
}

func main() {
    f := fibonacci()
    for i := 0; i < 10; i++ {
        fmt.Println(f())
    }
}
  • Congratulations!

You have completed this course!

You can return to [[/ list] [list of modules]] to see what the next learning, or continue [[ JavaScript: the Click ( '.next-Page')] [behind the course]].

Guess you like

Origin www.cnblogs.com/pdev/p/10928735.html