首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
GeekHub
xmge
V2EX  ›  程序员

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

  •  
  •   xmge · 17 天前 · 1849 次点击
    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 条附言  ·  17 天前
    1 、s[0] = "a" 会报错,所以 append 之前 slice 并不可使用,应该是 apend 时进行了初始化
    2 、0 切片,nli 切片,空切片的概念: http://www.meirixz.com/archives/80658.html

    v2 大佬就是多,解决问题就是快。感谢大佬。
    如果上面的解释有什么问题,欢迎大佬指出,或则有什么更容易理解的说法,也请赐教。
    第 2 条附言  ·  17 天前
    append 函数源码中的注释:

    ```
    // The append built-in function appends elements to the end of a slice. If
    // it has sufficient capacity, the destination is resliced to accommodate the
    // new elements. If it does not, a new underlying array will be allocated.
    // Append returns the updated slice. It is therefore necessary to store the
    // result of append, often in the variable holding the slice itself:
    // slice = append(slice, elem1, elem2)
    // slice = append(slice, anotherSlice...)
    // As a special case, it is legal to append a string to a byte slice, like this:
    // slice = append([]byte("hello "), "world"...)
    func append(slice []Type, elems ...Type) []Type
    ```
    17 条回复    2020-03-23 17:28:33 +08:00
    baiyi
        1
    baiyi   17 天前
    这应该算语言特性?

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

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

    https://play.golang.org/p/e6TsC_5Jk_B
    l1905
        9
    l1905   17 天前
    先看下 append 的定义, 是先判断 cap, 长度不够, 直接 copy 出为新 slice
    https://blog.golang.org/slices-intro

    xmge
        10
    xmge   17 天前
    @ty4z2008 @janxin @l1905 感谢大佬~\(≧▽≦)/~
    mengzhuo
        11
    mengzhuo   17 天前
    append 的语法糖
    reus
        12
    reus   17 天前
    append 会初始化 nil slice,而 map 和 chan 就没有 append 函数去做这个事情
    你的代码里,slice 的“使用”是调用了函数的,而 map 和 chan 就没有
    fcten
        13
    fcten   17 天前
    说 append 会初始化是不准确的,其实 append 直接返回了一个新的 slice 给你
    lcj2class
        14
    lcj2class   17 天前
    go tool compile -S xx.go
    编译看下就知道了,会调用 runtime.growslice 来创建一个。
    123444a
        15
    123444a   17 天前 via Android
    append 这么简单的定义,看来你开始是理解错了
    epson3333
        16
    epson3333   17 天前
    老哥啥时候发多个政治贴
    xmge
        17
    xmge   17 天前
    @epson3333 ??? 没听明白
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   3128 人在线   最高记录 5168   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 13:53 · PVG 21:53 · LAX 06:53 · JFK 09:53
    ♥ Do have faith in what you're doing.