4.数据
4.1 Array
4.2 Slice
4.2.1 reslice
4.2.2 append
4.2.3 copy
4.3 map
4.4 struct
4.4.1 匿名字段
4.4.2 面向对象
1.通常以 2 倍容量重新分配底层数组。在大批量添加数据时,建议一次性分配足够大的空间,以减少内存分配和数据复制开销。或初始化足够长的len 属性,改用索引号进行操作。及时释放不再使用的 slice 对象,避免持有过期数组,造成 GC 无法回收。
s := make([]int, 0, 1)
c := cap(s)
for i := 0; i < 50; i++ {
s = append(s, i)
if n := cap(s); n > c {
fmt.Printf("cap: %d -> %d\n", c, n)
c = n
}
}
输出:
i= 1 , cap 1 -> 2
i= 2 , cap 2 -> 4
i= 4 , cap 4 -> 8
i= 8 , cap 8 -> 16
i= 16 , cap 16 -> 32
i= 32 , cap 32 -> 64
i= 2 , cap 2 -> 4
i= 4 , cap 4 -> 8
i= 8 , cap 8 -> 16
i= 16 , cap 16 -> 32
i= 32 , cap 32 -> 64
2.从 map 中取回的是一个value 临时复制品,对其成员的修改是没有任何意义的。
type user struct{ name string }
m := map[int]user{ // 当 map 因扩张⽽重新哈希时,各键值项存储位置都会发⽣改变。 因此, map
1: {"user1"}, // 被设计成 not addressable。 类似 m[1].name 这种期望透过原 value
} // 指针修改成员的⾏为⾃然会被禁⽌。
m[1].name = "Tom" // Error: cannot assign to m[1].name
正确做法是完整替换value或使用指针
u := m[1]
u.name = "Tom"
m[1] = u // 替换 value。
m2 := map[int]*user{
1: &user{"user1"},
}
m2[1].name = "Jack" // 返回的是指针复制品。透过指针修改原对象是允许的。
3.面向对象三大特征里,Go仅支持封装,尽管匿名字段的内存布局和行为类似继承。没有class关键字,没有继承、多态等。
type User struct {
id int
name string
}
type Manager struct {
User
title string
}
m := Manager{User{1, "Tom"}, "Administrator"}
// var u User = m // Error: cannot use m (type Manager) as type User in assignment
// 没有继承,⾃然也不会有多态。
var u User = m.User // 同类型拷⻉。