4

go append 的疑问

 1 year ago
source link: https://www.v2ex.com/t/919461
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

V2EX  ›  Go 编程语言

go append 的疑问

  wuhaoecho · 5 小时 6 分钟前 · 820 次点击
package main

import "fmt"

func main() {
	// create a slice from an array
	x := [3]string{"A", "B", "С"}
	s := x[:] // a slice referencing the storage of x
	// x[1] = "O"
	t := append(s, "D") // append items to slice s
	x[1] = "O"
	fmt.Println("%+v", x)
	fmt.Println("%+v", s)
	fmt.Println("%+v", t)
}

https://go.dev/play/p/g-eGRJLteAH

t 为什么是 [A B С D]

我的理解是 t 在 s 的基础上加了个‘D' , x 改了 s, t 也要跟着变啊.

34 条回复    2023-02-27 14:57:00 +08:00
wuhaoecho

wuhaoecho      5 小时 3 分钟前

https://pkg.go.dev/builtin#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:

If it does not, a new underlying array will be allocated. 草
nickchenyx

nickchenyx      4 小时 59 分钟前 via Android

不然 append 为啥会返回一个新 arr 给你持有呢?最好的实践就是一直用最新的 arr 变量,别去动之前的
wuhaoecho

wuhaoecho      4 小时 59 分钟前

感觉是个坑啊

```
package main

import "fmt"

func main() {
// create a slice from an array
x := make([]string, 3, 10)
x[0] = "A"
x[1] = "B"
x[2] = "C"
s := x[:] // a slice referencing the storage of x
t := append(s, "D") // append items to slice s
x[1] = "O"
fmt.Println("%+v", x)
fmt.Println("%+v", s)
fmt.Println("%+v", t)
}
````

https://go.dev/play/p/MLJ9L4o7UQq
wuhaoecho

wuhaoecho      4 小时 57 分钟前   ❤️ 1

@nickchenyx #2 所谓最佳实践就是用来掩盖语言设计缺陷的.

从我不多的 golang 经验看, 这个 append 绝对咬过不少人.
beidounanxizi

beidounanxizi      4 小时 54 分钟前   ❤️ 1

append 是这样的 里面有个 growslice 扩容机制 memcopy 变成新数组的过程
1343EFF

1343EFF      4 小时 54 分钟前

看着像 php 的风格哈哈哈返回一个新的数组而不是让你引用旧的
wuhaoecho

wuhaoecho      4 小时 51 分钟前

@nickchenyx #2 我以为是在原有 arr 的基础上去扩展.

看来是

如果原来的 arr 够用, 就直接在上面扩展
不够就会新创建一个 arr(把数据 copy 过去).
wuhaoecho

wuhaoecho      4 小时 49 分钟前

@1343EFF #6 坑在于 如果原来的是容量够, 就是引用旧的. 我觉得每个 golang 程序员都要被咬一次
wuhaoecho

wuhaoecho      4 小时 48 分钟前

@beidounanxizi #8 多谢, 普通使用要看原理, 说明设计是不够自然.
Maboroshii

Maboroshii      4 小时 48 分钟前

是这样的啊,要不然就是 array.append 方法了。而且一般写代码如果这样写,看代码的人都要晕了,一会儿旧一会儿新的。。
cmdOptionKana

cmdOptionKana      4 小时 44 分钟前   ❤️ 1

@wuhaoecho 语言怎么设计,有得有失,比如设计成 Java 那样,确实低级坑是少一点,但内存占用就会大。

Go 希望编译速度快、运行效率高,自然就会要求程序员多费点心思。

像 C/C++, Rust 之类,低级坑更多,需要程序员耗费精神自己小心处理的地方更多,但运行效率也更高。
wuhaoecho

wuhaoecho      4 小时 42 分钟前

@cmdOptionKana #12 统一你的观点, 所以我觉得 golang 是比 java 更难的语言, 多了一层 pointer, 弄出来很多“似是而非”的问题.
cmdOptionKana

cmdOptionKana      4 小时 37 分钟前

@wuhaoecho 我感觉难度差别很细微,各有各的难点,Java 也有一些很复杂的地方。

C++, Rust 是难度高得很明显,但如果 Go 和 Java 比,就算说 Go 难,但难那么一点点,几乎可以忽略不计。
hzjseasea

hzjseasea      4 小时 36 分钟前

op 真的是边骂边学 golang...
MoYi123

MoYi123      4 小时 34 分钟前   ❤️ 1

@wuhaoecho 不是 go 比 java 多了指针, 而是 java 比 go 少了指针.
wuhaoecho

wuhaoecho      4 小时 33 分钟前

@cmdOptionKana #14 我虽然写的 java 不多, 但是不记得有什么困惑, golang 感觉老搞不清. 虽然也能写, 老觉得这样写是不是符合“标准”, java python 这些从来没有这样的困惑. rust c++ 跟 go java 不是一个层次的, 难是预期之内的.
wuhaoecho

wuhaoecho      4 小时 31 分钟前

@hzjseasea #15 没办法啊, 生活所迫, 我要是 python 能找到理想的工作才不会学 golang, 不过我把可以骂的点, 都搞清楚了, 就学会了么.
lesismal

lesismal      4 小时 27 分钟前

c 时代的 realloc 就是这样的,只是那些语言为了搬砖效率封装了一大堆、然后圈养了大批 CURDer
hzjseasea

hzjseasea      4 小时 26 分钟前

@wuhaoecho 我之前也是 python 转的 go,那时候还偶尔看点 rust ,当时给我的感觉就是卧槽这才是代码,python 太多东西给你封装起来 你写代码的时候压根看不见,现在把这些封装的都抛出来让你自己管理了,就觉得这也不好那也不好了... 像 go 的 map slice map channel 这四块都可以去了解下源码, 反正你找工作也要了解的
lesismal

lesismal      4 小时 25 分钟前

@MoYi123
> 不是 go 比 java 多了指针, 而是 java 比 go 少了指针.

这话说的妙极了
wuhaoecho

wuhaoecho      4 小时 20 分钟前

@hzjseasea #20 大佬你适合去搞汇编
wuhaoecho

wuhaoecho      3 小时 53 分钟前

https://books.studygolang.com/GoExpertProgramming/chapter01/1.2-slice.html

https://go.dev/play/p/mgax2-QsRKI

package main

import (
"fmt"
)

func AddElement(slice []int, e int) []int {
return append(slice, e)
}

func main() {
var slice []int
slice = append(slice, 1, 2, 3)

newSlice := AddElement(slice, 4)
fmt.Println(&slice[0] == &newSlice[0])
}


专家都搞不清

我一个新手很快能摸到坑也是不容易.
Nazz

Nazz      3 小时 29 分钟前 via Android

设计成 OOP 风格明显会更好,之所以没有大概是因为泛型
hsfzxjy

hsfzxjy      3 小时 21 分钟前 via Android

学过 c 的就感觉很自然,类似 realloc 的行为
wuhaoecho

wuhaoecho      3 小时 19 分钟前 via Android

@lesismal less is more go 语言的爹经常说的
leonshaw

leonshaw      3 小时 9 分钟前

像 rust 的 ownership 一样,自己制定一些规则,例如只能通过一个 owner slice append ,append 以后其它相关 slice 都失效。
zagfai

zagfai      2 小时 24 分钟前

@lesismal 为什么觉得是圈养了 curder 而不是技术发展提高了生产力了?现在没人钻木取火了吧?
lanlanye

lanlanye      2 小时 23 分钟前

因为 slice 底下是固定大小的数组,不够了要扩容+copy ,你可以试试用 make 来指定底层数组的大小,只要不超过这个大小就不会出现问题。
但归根结底,不知道这个就容易踩坑。
lesismal

lesismal      2 小时 23 分钟前

@wuhaoecho
go 爹说的没毛病,我的这个 id (les is mal)也是 less is more 缩写拼接变换得到的
很多人嘲讽 go 大道至简,殊不知是他们习惯了搬砖的工作、而 go 不是只为了简单搬砖。。。
lesismal

lesismal      2 小时 21 分钟前

先走出自己的舒适区,然后不知不觉就破境了
lesismal

lesismal      2 小时 1 分钟前

@zagfai
你看 #19 我那句的完整顺序:
1. 先说的 “为了搬砖效率” —— 这个就是提高了部分生产力,因为提高的主要是开发效率 /速度、性能和软硬件消耗的成本是不划算的
2. 然后才说的“圈养了大批 CURDer”

科技线的演化规律通常是不同技术潮涨潮落逐步更迭到更好的,相比于 java ,go 的性能和消耗更友好,目前在一些其他语言舒适区使用者眼里,go 开发效率差很多,但毕竟出生的晚,随着逐步完善、开发效率越来越高,而且就我自己而言从来没觉得用 go 比用其他语言开发效率低。

但 go 性能不够强,只能做第二梯队、在开发效率与性能消耗之前均衡,在 CURD 与基础设施以及这两者的一些中间过渡领域会有很多作为。

往远一点看,rust 会大量占市场,目前阶段是 rust 已经进入,比如 linux 内核,比如 tidb 这种搞数据库的,比如 cloudflare 的一些基础设施:
https://mp.weixin.qq.com/s/1dB4P54tVz-aM2iYIkE4fg

再往远一点看,AI 的发展,未来大部分代码可能会是由 AI 直接生成更高性能的机器码,等到 NLP 、AI 编码更牛逼了,人类需求直接丢给 AI 了,配合上更丰富完善的测试验收体系。全盘丢给 AI 怕它作恶像终结者那样反噬人类,所以你看,OpenAI 的核心宗旨在于“实现安全的通用人工智能(AGI)”,使其有益于人类

性能是效率的永恒核心,是生产力的核心,现阶段你觉得够用了,并不代表其他人、next gen 也觉得性能够用。所以不要觉得 java 那些提高了生产力就没必要 go 和 rust 了,那只是 CURDer 这些不需要性能的人在坐井观天或者自欺欺人罢了
lesismal

lesismal      1 小时 55 分钟前

@zagfai
go rust 或者 c/cpp ,不是钻木取火。
如果这些是钻木取火,未来 AI 写代码成熟了,那时候的人同样也会说用 java php 这些是钻木取火、谁还自己写代码啊!?

过去这十几年,IT 这条线发展太快了,不知道 AI 迭代的速度会有多快,有生之年是否能见识到机器生命雏形甚至更高阶一点:joy:

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK