返回信息流对于go中的slice很不能理解,为什么要有一下这种操作
a := []int
a = append(1)
看了下网上的解释,说slice可以理解成一个封装了底层数组和len和cap的结构体,既然如此,如果append超出了cap,底层重新创建了一个新的数组,那就在下面用新的数组替换掉结构体里的数组不好吗,为什么要把整个结构体都替换掉
直接append(1)这样的语法不会更简单美好吗?
这是一条镜像帖。来源:北邮人论坛 / golang / #1059同步于 2018/5/7
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Golang机器人发帖
来自java程序员对于go中slice的提问
cc19931002
2018/5/7镜像同步9 回复
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
你这语法都错了吧 a = append(a, 1)
结构体并没有替换掉 你打印这个地址还是一样的 只是数据的地址换了 其实和C++的vector是类似的
嗯,对,语法错了,如果整个a没有替换掉,为什么要 a = append(a,1),直接append(a,1)不就好了吗
【 在 duduscript 的大作中提到: 】
: 你这语法都错了吧 a = append(a, 1)
: 结构体并没有替换掉 你打印这个地址还是一样的 只是数据的地址换了 其实和C++的vector是类似的
1. go是门比较强制风格的语言,比如if后必须加大括号,人家可以就喜欢这么干;
2. slice里封装的只是数组的指针而不是整个数组,跟java本质不同的是go是有指针的语言,通过函数改变内存分配空间必须要用指针,采用你说的那种方法实现,就得像写C/C++一样写成append(&arr, 1),但go语言设计者并不希望go程序员像C/C++程序员那样频繁操作指针,大量使用指针降低开发效率,更不容易调试;
3. 保持状态变量immutable更线程安全;
a是被替换的 slice的本质是一个三元组 (ptr, len, cap), append的API是 func append(slice []Type, elems ...Type) []Type
b = append(a, 1)
这个返回值的ptr有可能和a一样 也有可能不一样
给你一个例子你跑一下:
```go
var a, b []int
a = append(a, 1)
for i := 1; i < 10; i++ {
b = append(a, 1)
fmt.Println("a:", &a[0], len(a), a)
fmt.Println("b:", &b[0], len(b), b)
a = append(a, 2)
b[0] = i + 10
fmt.Println("a:", &a[0], len(a), a)
fmt.Println("b:", &b[0], len(b), b)
fmt.Println()
}
```
C++和Java程序员看这个结果可能有些反直觉 哈哈 算是golang的feature
golang不是面向对象的 你要分清楚这个append(a, 1) 和 a.append(1)是有区别的
【 在 cc19931002 的大作中提到: 】
: 嗯,对,语法错了,如果整个a没有替换掉,为什么要 a = append(a,1),直接append(a,1)不就好了吗
【 在 duduscript 的大作中提到: 】
: 我之前说的没有替换是a = append(a, 1) 这个a还是这个a的地址 你循环多少次 a这个slice的三元组的地址不会变
小姐姐厉害了[ema3]
【 在 duduscript 的大作中提到: 】
: 我之前说的没有替换是a = append(a, 1) 这个a还是这个a的地址 你循环多少次 a这个slice的三元组的地址不会变
跑了一下,有时候四个输出地址都相同= =,a = append(a,1),然后a的地址也会变,请问这是什么回事[ema1]
我这边a的地址也会变。
【 在 w1252675615 的大作中提到: 】
:
: 跑了一下,有时候四个输出地址都相同= =,a = append(a,1),然后a的地址也会变,请问这是什么回事