操作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
    //    }
    //  ...
    //}

最后更新于

这有帮助吗?