我又来了,代码如下:
s1和s2 都是空切片,长度都为零,为何跟nil比较结果不一样呢?
package main
import "fmt"
func main() {
var s1 = []string{}
var s2 []string
fmt.Println(s1 == nil, s1, len(s1)) // 输出 false [] 0
fmt.Println(s2 == nil, s2, len(s2)) // 输出 true [] 0
}
有疑问加站长微信联系(非本文作者)

明白了,s1相当于已经做一次初始化,已经分配内存了,就不等于nil
这种用法是不对的,不应该对slice进行nil判断,应该进行len()取长度
切片本质不是引用类型么,为何不能和nil比较?
谁告诉你是引用,你先看看slice的数据结构,而且nil并不是你想象的nil,这里的nil是零值,并不是空
你好,我还是不太理解。
就像下面这个例子,操作函数没有返回值,直接对切片进行操作,这个不是引用类型?
5楼 @sharkLoc
这个代码应该可以足够说明
6楼 @liangmanlin 回六楼:demo前后内容不变,参考 https://golang.google.cn/blog/slices-intro 切片是引用类型。
所以你还不理解?如果是引用,为什么不变,因为slice不是引用,他是一个结构体
兄弟,你还是停留在表面啊,试试下边的代码
别人说的没错是传递的结构体。去golang源码可以找到slice的源码
所以len(切片),cap(切片)可以获取到长度。
结构体中的unsafe.Pointer是指向底层数组的真实地址。 你的mytest方法传递就是结构体副本。不过因为他们各自的slice切片结构体的地址值一样,所以操作的数组能够更改。
修改下你的方法,就会说明go切片的传递就是拷贝的结构体
运行结果如下
之所以demo的切片不是 [1 2 3 4 0],是因为mytest的append发生了扩容,导致x切片中的unsafe.Pointer发生改变了。但这并不会影响到demo切片。因为这两个切片结构体根本不是一个对象
至少, golang 没有c++概念的引用。因为传递slice值仅仅是复制slice的结构体。虽然底层的数组是一个。但是slice却不是一个。 golang不存在共用一个内存地址的不同变量。因此golang没有引用。
老哥,是你停留在表面。。。。
说明啥?先弄明白append 再说
没错,切片底层确实是一个结构体,但是这个结构体可以理解为底层数组的引用。此引用当然跟C++的引用不是一样的概念,你可以搜一下goalng的引用类型,开发者已经约定成俗的认为slice、map和channel为引用类型了。你上边说slice不能与nil做比较是不对的,因为slice只有在new或者make之后才会分配内存,只是var s []int,这样的话,s确实是nil。还有你贴出来的代码,想证明slice不是引用,也是不对的,结果不变只是因为底层数组扩容导致了指针改变,而不能说明slice不是引用。
附加一句,nil并不是空指针,是goalng特有的类型,并且这里的引用类型也不能理解为C++的引用。
这个其实很好理解,首先是s1这个是相当于赋值了,等于make了一下就在内存中开辟了一个空间,所有它的内存地址是有的就不等于nil了,s2则反之并没有开辟内存空间所以是nil,这里说明一下切片是引用类型必须要先申明内存空间之后才能使用
首先,go的函数传参,返回都是拷贝。你可以把它理解成一个浅拷贝,而slice底层确实是结构体,函数修改的虽然是拷贝的数据,但是由于是浅拷贝,原来的slice和函数里的slice虽然不一样,但是共用同一个数组,只是通过下标修改值当然不会影响到底层的数组了啊!append扩容了之后,函数里面的slice绑定了一个新数组,当然不会影响到元slice了。

对应的内存地址空间不一样,所以不相等。