dongzhu3548 2018-10-06 17:50
浏览 32
已采纳

切片和贴图之间的行为差​​异

A related questions is here https://stackoverflow.com/a/12965872/6421681.

In go, you can do:

func numsInFactorial(n int) (nums []int) {
    // `nums := make([]int)` is not needed
    for i := 1; i <= n; i++ {
        nums = append(nums, i)
    }
    return
}

However,the following doesn't work:

func mapWithOneKeyAndValue(k int, v int) (m map[int]int) {
    m[k] = v
    return
}

An error is thrown:

panic: assignment to entry in nil map

Instead, you must:

func mapWithOneKeyAndValue(k int, v int) map[int]int {
    m := make(map[int]int)
    m[k] = v
    return
}

I can't find the documentation for this behavior. I have read through all of effective go, and there's no mention of it there either.
I know that named return values are defined (i.e. memory is allocated; close to what new does) but not initialized (so make behavior isn't replicated).
After some experimenting, I believe this behavior can be reduced into understanding the behavior of the following code:

func main() {
    var s []int // len and cap are both 0
    var m map[int]int

    fmt.Println(s) // works... prints an empty slice
    fmt.Println(m) // works... prints an empty map

    s = append(s, 10) // returns a new slice, so underlying array gets allocated
    fmt.Println(s) // works... prints [10]

    m[10] = 10 // program crashes, with "assignment to entry in nil map"
    fmt.Println(m)
}

The issue seems that append likely calls make and allocates a new slice detecting that the capacity of s is 0. However, map never gets an explicit initialization.
The reason for this SO question is two-pronged. First, I would like to document the behavior on SO. Second, why would the language allow non-initializing definitions of slice and map? With my experience with go so far, it seems to be a pragmatic language (i.e. unused variables lead to compilation failure, gofmt forces proper formatting), so it would make sense for it to prevent the code from compiling.

  • 写回答

2条回答 默认 最新

  • dongtiaobeng7901 2018-10-06 17:59
    关注

    Try to assign in nil slice by index - you will get "panic: runtime error: index out of range" (example: https://play.golang.org/p/-XHh1jNyn5g)

    The only reason why append function works with nil, is that append function can do reallocation for the given slice. For example, if you trying to to append 6th element to slice of 5 elements with current capacity 5, it will create the new array with new capacity, copy all the info from old one, and swap the data array pointers in the given slice. In my understanding, it is just golang implementation of dynamic arrays.

    So, the nil slice is just a special case of slice with not enough capacity, so it would be reallocated on any append operation.

    More details on https://blog.golang.org/go-slices-usage-and-internals

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料