Go 中为什么切片不用初始化就可以使用

2020-03-23 08:59:03 +08:00
 xmge
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"
}
5214 次点击
所在节点    程序员
17 条回复
baiyi
2020-03-23 09:26:46 +08:00
这应该算语言特性?

slice 在 append 调用的方法中判断了一下,如果没有初始化的底层数组指针,就新建一个。
pennchester
2020-03-23 09:37:41 +08:00
你这样创建的是 nil 切片,切片是个特殊的引用类型,var s []string 这种声明会指向的一个为 0 的地址,你可以参考一下这篇文章
http://www.meirixz.com/archives/80658.html
xmge
2020-03-23 09:40:26 +08:00
@baiyi 可能是吧。在 append 之前调用 len()或 cap()结果都是 0 。在网上搜索答案都是 make 或者显示创建来初始化,之前也一直有这疑问,但是没有深追。
gbanbo
2020-03-23 09:43:21 +08:00
你把 s = append(s, "a")改成 s[0] = "a"就知道了,和下面的 map 一样会 panic,append 只是帮你判断,如果是 nil 就帮你 make 了。
xmge
2020-03-23 09:52:21 +08:00
@gbanbo @pennchester 好的,感谢大佬 ~\(≧▽≦)/~
pennchester
2020-03-23 10:00:12 +08:00
@gbanbo 其实你这个不是很准确,你这个会报错是因为越界了,你用 make 产生的切片,容量设为 0,同样会报错的
ty4z2008
2020-03-23 10:02:44 +08:00
https://blog.golang.org/slices-intro

这个是因为 append 内部实现了 slice 的自增。与此类似的函数还有 copy 。这两个函数内部都进行 make 初始化。每次对 slice 的操作内部是会产生一个新的数组,然后返回
janxin
2020-03-23 10:03:17 +08:00
其实你这个疑问可以跑个程序输出一下就明白了

https://play.golang.org/p/e6TsC_5Jk_B
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
xmge
2020-03-23 10:12:49 +08:00
@ty4z2008 @janxin @l1905 感谢大佬~\(≧▽≦)/~
mengzhuo
2020-03-23 10:13:34 +08:00
append 的语法糖
reus
2020-03-23 10:50:09 +08:00
append 会初始化 nil slice,而 map 和 chan 就没有 append 函数去做这个事情
你的代码里,slice 的“使用”是调用了函数的,而 map 和 chan 就没有
fcten
2020-03-23 11:00:56 +08:00
说 append 会初始化是不准确的,其实 append 直接返回了一个新的 slice 给你
lcj2class
2020-03-23 11:13:36 +08:00
go tool compile -S xx.go
编译看下就知道了,会调用 runtime.growslice 来创建一个。
123444a
2020-03-23 15:46:38 +08:00
append 这么简单的定义,看来你开始是理解错了
epson3333
2020-03-23 16:49:46 +08:00
老哥啥时候发多个政治贴
xmge
2020-03-23 17:28:33 +08:00
@epson3333 ??? 没听明白

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/655229

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX