操作map、slice的nil对象
//为什么声明一个切片就能直接使用,如:
// var s []int64
// s.append(1)
//
//而如果:
// var m map[int]string
//需要再make,才能存储kv, 否则panic?
var x []int
fmt.Println(x == nil) // true
// var u uintptr
// fmt.Println(u) // 0
// {Data:0 Len:0 Cap:0}
fmt.Printf("声明一个slice %+v\n", *(*reflect.SliceHeader)(unsafe.Pointer(&x)))
x = append(x, 1) // CALL runtime.growslice(SB)
var mp map[int]int
fmt.Println(mp == nil) // true
// mp[1] = 1 // panic: assignment to entry in nil map
mp = make(map[int]int)
mp[1] = 1 // CALL runtime.mapassign_fast64(SB)
// 反汇编后我们看到:
// 1. 对slice执行append调用 runtime.growslice // 可以在src/runtime/slice.go中找到
//func growslice(et *_type, old slice, cap int) slice {
// ...
// if et.ptrdata == 0 {
// p = mallocgc(capmem, nil, false) // 分配内存
// ...
// }
//}
// 2. 对于map执行mp[key] = value调用 runtime.mapassign_fast64 // 可以在src/runtime/map_fast64找到
//func mapassign_fast64(t *maptype, h *hmap, key uint64) unsafe.Pointer {
// if h == nil {
// panic(plainError("assignment to entry in nil map")) // 如果为nil直接panic
// }
// ...
//}
最后更新于
这有帮助吗?