• Darren
    2021-11-15
    课后题测试代码如下: var sl1 []int var sl2 = []int{} fmt.Print("========基本区别=========\n") fmt.Printf("%v,len:%d,cap:%d,addr:%p\n", sl1, len(sl1), cap(sl1), &sl1) fmt.Printf("%v,len:%d,cap:%d,addr:%p\n", sl2, len(sl2), cap(sl2), &sl2) fmt.Printf("sl1==nil:%v\n", sl1 == nil) fmt.Printf("sl2==nil:%v\n", sl2 == nil) a1 := *(*[3]int)(unsafe.Pointer(&sl1)) a2 := *(*[3]int)(unsafe.Pointer(&sl2)) fmt.Print("========底层区别=========\n") fmt.Println(a1) fmt.Println(a2) type SliceDemo struct { Values []int } var s1 = SliceDemo{} var s2 = SliceDemo{[]int{}} bs1, _ := json.Marshal(s1) bs2, _ := json.Marshal(s2) fmt.Print("========序列化区别=========\n") fmt.Println(a1) fmt.Println(string(bs1)) fmt.Println(string(bs2)) ========基本区别========= [],len:0,cap:0,addr:0xc0000a6018 [],len:0,cap:0,addr:0xc0000a6030 sl1==nil:true sl2==nil:false ========底层区别========= [0 0 0] [18601168 0 0] ========序列化区别========= [0 0 0] {"Values":null} {"Values":[]} 可以看到,日常的使用基本是没有区别的,只不过与nil的比较,以及底层数据结构和序列化还是有一定的区别的。 同时go官方推荐使用 var sl1 []int The former declares a nil slice value, while the latter is non-nil but zero-length. They are functionally equivalent—their len and cap are both zero—but the nil slice is the preferred style. 在goland开发时,第二种声明方式会出现黄色下划线,提示需要改动。
    展开

    作者回复: 思考题完成的很细致,很全面。手动点赞!

    共 6 条评论
    80
  • 在下宝龙、
    2021-11-15
    var sl1 []int var sl2 = []int{} s1是声明,还没初始化,是nil值,底层没有分配内存空间。 s2初始化了,不是nil值,底层分配了内存空间,有地址。 我是这么理解的。

    作者回复: 正确✅

    
    47
  • trietree
    2021-11-15
    sl1未初始化,值为nil,和nil比较返回true sl2初始化为empty slice,和nil比较返回false

    作者回复: 正确✅

    
    14
  • 风铃
    2022-02-23
    个人感觉,在初始化切片的时候,最好的分配项目的需求,分配一定的容量(cap),要不在切片里面的数据多了,每次进行扩容,会消耗大量的内存性能

    作者回复: 👍。

    共 3 条评论
    9
  • 松
    2022-01-28
    有个疑问,切片的底层数组,在切片发生自动扩容后,在物理空间上还是连续的吗?

    作者回复: 扩容是新分配一段连续的大点的内存,原先的内存块不要了。所以依旧是连续的。

    共 4 条评论
    8
  • 笑忘日月星辰
    2022-06-25
    老师好,关于扩容,麻烦解惑下 问题:扩容当小于1024时候,是扩容为当前的2倍;当大于1024小于1280时候扩容为1.25倍,当大于1280小于1696时候,扩容为1.325倍吗?这个扩容的规则是什么? func main() { var s []int for i := 0; i < 2048; i++ { s = append(s, i) fmt.Println(len(s), cap(s)) } } 打印结果 --------------------------------------------------- 512 512 513 1024 ... 1024 1024 1025 1280 ... 1280 1280 1281 1696 ... 1696 1696 1697 2304 ...

    作者回复: 你用的是什么版本的go编译器,go 1.18,如果是go 1.18,那么可以看https://mp.weixin.qq.com/s/4wYrwBwnuylSvTaxBMXUgg ,go 1.18对slice的扩容算法了调整。

    
    4
  • 左卫康
    2022-08-05 来自北京
    思考题:var sl1 []int 仅声未初始化,值为对应类型的零值,nil var sl2 = []int{} 声明并初始化,是个空切片

    作者回复: ✅

    
    3
  • 和白白
    2022-03-07
    var sl1 []int 不显示初始化,所以 sl1 对应 slice 的零值 nil,并且此时没有 ptr、len 和 cap var sl2 = []int{} 显示初始化,sl2 对应 [] 空数组,ptr 指定空数组的地址,len 和 cap 都是 0

    作者回复: ✅

    
    3
  • 布凡
    2021-11-15
    老师,请问下为什么go没有class 这个类型呢?是因为想要开发者多用组合少用继承的设计理念吗?还是有其它原因呢?

    作者回复: class是面向对象语言的专有名词。go定位就不是oo语言,所以没有class。

    共 3 条评论
    3
  • Aeins
    2022-05-26
    sl1 自身有分配内存(能取地址),底层数组没有分配内存。为什么值会是 nil 呢?

    作者回复: 首先是否为nil与自身是否能取地址无关。 var p *int = nil println(&p) // 这取地址也是可以的。 切片是复合数据类型,如果其没有被初始化,那么go语言规定其默认的零值就为nil。

    
    2