More types structs, slices, and maps
structs 结构体
Pointers to structs
Struct fields can be accessed through a struct pointer. 可以通过结构指针访问结构字段。
To access the field X of a struct when we have the struct pointer p we could write (*p).X. However, that notation is cumbersome, so the language permits us instead to write just p.X, without the explicit dereference. 当我们拥有结构指针 p 时,要访问结构的字段 X ,我们可以编写 (*p).X 。然而,这种表示法很麻烦,所以该语言允许我们只写 p.X ,而无需显式取消引用。
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)
}
Struct Embedding结构体嵌入
type base struct {
num int
}
type container struct {
base
str string
}
上面这段就是结构体嵌入,在使用字面量来声明结构时候,需要显式传入初始化的值
co := container{
base: base{
num: 1,
},
str: "some name",
}
如果同时base结构体实现了接口,那么container也可以使用这个接口
type describer interface {
describe() string
}
func (b base) describe() string {
return fmt.Sprintf("base with num=%v", b.num)
}
slices
An array has a fixed size. A slice, on the other hand, is a dynamically-sized, flexible view into the elements of an array. In practice, slices are much more common than arrays. 数组具有固定大小。另一方面,切片是对数组元素的动态大小、灵活的视图。实际上,切片比数组更常见。
The type []T is a slice with elements of type T.
[]T 类型是一个包含 T 类型元素的切片。
A slice is formed by specifying two indices, a low and high bound, separated by a colon: 通过指定两个索引(下限和上限)来形成切片,用冒号分隔:
Slices are like references to arrays切片类似于数组的引用
A slice does not store any data, it just describes a section of an underlying array. 切片不存储任何数据,它只是描述底层数组的一部分。
Changing the elements of a slice modifies the corresponding elements of its underlying array. 更改切片的元素会修改其底层数组的相应元素。
func main() {
names := [4]string{
"John",
"Paul",
"George",
"Ringo",
}
fmt.Println(names)
a := names[0:2]
b := names[1:3]
fmt.Println(a, b)//[John Paul] [Paul George]
b[0] = "XXX"
a[1] = "new a"
fmt.Println(a, b)//[John new a] [new a George]
fmt.Println(names)//[John new a George Ringo]
}
Slice literals 切片字面量
type Vertex struct {
i int
b bool
}
func main() {
q := []int{2, 3, 5, 7, 11, 13}
fmt.Println(q)
r := []bool{true, false, true, true, false, true}
fmt.Println(r)
var nr = &r
(*nr)[1] = true
fmt.Println(r)//[true true true true false true]
s := []Vertex{
{2, true},
{3, false},
{5, true},
{7, true},
{11, false},
{13, true},
}
fmt.Println(s)//[{2 true} {3 false} {5 true} {7 true} {11 false} {13 true}]
}
Slice defaults
The default is zero for the low bound and the length of the slice for the high bound. 下限的默认值为零,上限的切片长度为默认值。
Slice length and capacity 切片长度和容量
A slice has both a length and a capacity. 切片具有长度和容量。
The length of a slice is the number of elements it contains. 切片的长度是它包含的元素的数量。
The capacity of a slice is the number of elements in the underlying array, counting from the first element in the slice. 切片的容量是底层数组中元素的数量,从切片中的第一个元素开始计算。
The length and capacity of a slice s can be obtained using the expressions
Nil slices
The zero value of a slice is nil. 切片的零值为 nil 。
A nil slice has a length and capacity of 0 and has no underlying array. nil 切片的长度和容量为 0,并且没有底层数组。
func main() {
var s []int
fmt.Println(s, len(s), cap(s))//[] 0 0
if s == nil {
fmt.Println("nil!")
}
}
Creating a slice with make
The make function allocates a zeroed array and returns a slice that refers to that array: make函数分配一个零值数组并且返回一个引用该数组的slice
b := make([]int, 0, 5) // len(b)=0, cap(b)=5
slice of slices
Slices can contain any type, including other slices. 切片可以包含任何类型,包括其他切片。
func main() {
// Create a tic-tac-toe board.
board := [][]string{
[]string{"_", "_", "_"},
[]string{"_", "_", "_"},
[]string{"_", "_", "_"},
}
// The players take turns.
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], " "))
}
}
Appending to a slice 附加到切片
将新元素附加到切片是很常见的,因此 Go 提供了一个内置的 append 函数。内置包的文档描述了 append 。
func append(s []T, vs ...T) []T The first parameter s of append is a slice of type T, and the rest are T values to append to the slice. append 的第一个参数 s 是一个 T 类型的切片,其余参数是要附加到切片的 T 值。 The resulting value of append is a slice containing all the elements of the original slice plus the provided values. append 的结果值是一个切片,其中包含原始切片的所有元素加上提供的值。
If the backing array of s is too small to fit all the given values a bigger array will be allocated. The returned slice will point to the newly allocated array. 如果 s 的后备数组太小而无法容纳所有给定值,则会分配一个更大的数组。返回的切片将指向新分配的数组。
func main(){
var s init[]
s = append(s,0)
// We can add more than one element at a time.
s = append(s, 2, 3, 4)
}
Range 排列
The range form of the for loop iterates over a slice or map. for 循环的 range 形式迭代切片或映射。
When ranging over a slice, two values are returned for each iteration. The first is the index, and the second is a copy of the element at that index. 在切片上进行测距时,每次迭代都会返回两个值。第一个是索引,第二个是该索引处元素的副本。
var pow = init[]{1, 2, 4, 8, 16, 32, 64, 128}
for i,v := range pow {
fmt.Printf("2**%d = %d\n", i, v)
}
输出结果:
2**0 = 1
2**1 = 2
2**2 = 4
2**3 = 8
2**4 = 16
2**5 = 32
2**6 = 64
2**7 = 128
Maps
A map maps keys to values. 映射将键映射到值。
The zero value of a map is nil. A nil map has no keys, nor can keys be added. map的零值是 nil .nil 映射没有键,也不能添加键。
The make function returns a map of the given type, initialized and ready for use. make 函数返回给定类型的映射,已初始化并准备好使用。
package main
import "fmt"
//定义结构体
type Vertex struct {
Lat, Long float64
}
//声明m的类型为map,键值为string类型,值为Vertex类型
var m map[string]Vertex
func main() {
fmt.Println(m)
//通过make初始化m
m = make(map[string]Vertex)
m["Bell Labs"] = Vertex{
40.68433, -74.39967,
}
fmt.Println(m["Bell Labs"],m)
}
Map literals map字面量
If the top-level type is just a type name, you can omit it from the elements of the literal. 如果顶级类型只是一个类型名称,您可以从文字的元素中省略它。
type Vertex struct {
Lat, Long float64
}
var m = map[string]Vertex{
"Bell Labs": Vertex{40.68433, -74.39967},
"Google": {37.42202, -122.08408},
}
func main() {
fmt.Println(m)
}
Mutating Maps 改变map
Insert or update an element in map m: 在地图 m 中插入或更新元素:
m[key] = elem Retrieve an element: 检索元素:
elem = m[key] Delete an element: 删除一个元素:
delete(m, key) Test that a key is present with a two-value assignment: 测试一个键是否存在一个二值赋值:
elem, ok = m[key] If key is in m, ok is true. If not, ok is false. 如果 key 在 m 中,则 ok 是 true 。如果不是, ok 就是 false 。
If key is not in the map, then elem is the zero value for the map's element type. 如果 key 不在地图中,则 elem 是地图元素类型的零值。
Note: If elem or ok have not yet been declared you could use a short declaration form: 注意:如果尚未声明 elem 或 ok ,您可以使用简短的声明形式:
elem, ok := m[key]
m := make(map[string]int)
m["answer"] = 42
s,err := m["answer"]