var定义,在不赋值会有默认空值
不同类型的空值
int空值是0
string空值是""而不是null或者nil
Slice空值是长度为0的Slice而不是nil,
map空值是nil,
error空值是nil,
struct空值是一个“所有成员都是空值”的空Struct而不是nil
var 定义切片,map也是有默认值的
var a []string 长度为0的string数组,可以通过append往里面加值,var a map[string]interface{}的空值是nil,所以不能通过a["a"]="b"这样的方式进行赋值。
:=一定要初始化
new定义返回指针
a := new(int) #指向0值的指针
var a *int #nil
a := new([]string) #指向长度为0的string数组的指针
a := new(map[string]string) #指向空map(nil)的指针
new的内存申请时需要注意的问题
type Student struct { age *int } func main() { s := new(Student) *(s.age) = 10 # 运行报错,s.age为nil fmt.Println(s.age) }
new
只会为结构体Student申请一片内存空间,不会为结构体中的指针age申请内存空间,所以引用操作就因为访问无效的内存空间而出现panic
。
make定义主要为channel,切片,map赋值
slice := make([]int, 0, 100) hash := make(map[int]bool, 10) ch := make(chan int, 5)
深浅复制问题,需要对底层结构有足够的理解
切片和map底层都是指向数组的指针, 普通的复制都是浅复制,在修改值时会影响赋值的对象
对切片和map的深复制都需要预先定义大小
对切片的深复制
func (d *Driver) SetTrips(trips []Trip) { d.trips = make([]Trip, len(trips)) copy(d.trips, trips) } trips := ... d1.SetTrips(trips) // 这里我们修改 trips[0],但不会影响到 d1.trips trips[0] = ...
对map的深复制
type Stats struct { mu sync.Mutex counters map[string]int } func (s *Stats) Snapshot() map[string]int { s.mu.Lock() defer s.mu.Unlock() result := make(map[string]int, len(s.counters)) for k, v := range s.counters { result[k] = v } return result } // snapshot 现在是一个拷贝 snapshot := stats.Snapshot()
只有数组可以直接复制