package main import ( "fmt" ) func main() { // 可以使用 var s []string s = append(s, "a") fmt.Println(s) // 未初始化不可使用 var m map[string]string m["a"]= "b" fmt.Println(m) // 未初始化不可使用 var c chan string go func() { fmt.Println(<-c) }() c <- "a" }
![]() | 1 baiyi 2020-03-23 09:26:46 +08:00 这应该算语言特性? slice 在 append 调用的方法中判断了一下,如果没有初始化的底层数组指针,就新建一个。 |
![]() | 2 pennchester 2020-03-23 09:37:41 +08:00 你这样创建的是 nil 切片,切片是个特殊的引用类型,var s []string 这种声明会指向的一个为 0 的地址,你可以参考一下这篇文章 http://www.meirixz.com/archives/80658.html |
![]() | 3 xmge OP @baiyi 可能是吧。在 append 之前调用 len()或 cap()结果都是 0 。在网上搜索答案都是 make 或者显示创建来初始化,之前也一直有这疑问,但是没有深追。 |
4 gbanbo 2020-03-23 09:43:21 +08:00 你把 s = append(s, "a")改成 s[0] = "a"就知道了,和下面的 map 一样会 panic,append 只是帮你判断,如果是 nil 就帮你 make 了。 |
![]() | 5 xmge OP @gbanbo @pennchester 好的,感谢大佬 ~\()/~ |
![]() | 6 pennchester 2020-03-23 10:00:12 +08:00 @gbanbo 其实你这个不是很准确,你这个会报错是因为越界了,你用 make 产生的切片,容量设为 0,同样会报错的 |
![]() | 7 ty4z2008 2020-03-23 10:02:44 +08:00 https://blog.golang.org/slices-intro 这个是因为 append 内部实现了 slice 的自增。与此类似的函数还有 copy 。这两个函数内部都进行 make 初始化。每次对 slice 的操作内部是会产生一个新的数组,然后返回 |
![]() | 8 janxin 2020-03-23 10:03:17 +08:00 |
![]() | 9 l1905 2020-03-23 10:04:40 +08:00 先看下 append 的定义, 是先判断 cap, 长度不够, 直接 copy 出为新 slice https://blog.golang.org/slices-intro https://gist.github.com/l1905/424f15d629ee0dcdb5c4727c0c83559a |
11 mengzhuo 2020-03-23 10:13:34 +08:00 append 的语法糖 |
![]() | 12 reus 2020-03-23 10:50:09 +08:00 /div> append 会初始化 nil slice,而 map 和 chan 就没有 append 函数去做这个事情 你的代码里,slice 的“使用”是调用了函数的,而 map 和 chan 就没有 |
![]() | 13 fcten 2020-03-23 11:00:56 +08:00 说 append 会初始化是不准确的,其实 append 直接返回了一个新的 slice 给你 |
![]() | 14 lcj2class 2020-03-23 11:13:36 +08:00 go tool compile -S xx.go 编译看下就知道了,会调用 runtime.growslice 来创建一个。 |
15 123444a 2020-03-23 15:46:38 +08:00 via Android append 这么简单的定义,看来你开始是理解错了 |
![]() | 16 epson3333 2020-03-23 16:49:46 +08:00 老哥啥时候发多个政治贴 |