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
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
老哥啥时候发多个政治贴
|