The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
echoless

go append 的疑问

  •  
  •   echoless · Feb 27, 2023 · 2694 views
    This topic created in 1182 days ago, the information mentioned may be changed or developed.
    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 也要跟着变啊.

    41 replies    2023-02-28 12:40:21 +08:00
    echoless
        1
    echoless  
    OP
       Feb 27, 2023
    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
        2
    nickchenyx  
       Feb 27, 2023 via Android
    不然 append 为啥会返回一个新 arr 给你持有呢?最好的实践就是一直用最新的 arr 变量,别去动之前的
    echoless
        3
    echoless  
    OP
       Feb 27, 2023
    感觉是个坑啊

    ```
    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
    echoless
        4
    echoless  
    OP
       Feb 27, 2023   ❤️ 1
    @nickchenyx #2 所谓最佳实践就是用来掩盖语言设计缺陷的.

    从我不多的 golang 经验看, 这个 append 绝对咬过不少人.
    beidounanxizi
        5
    beidounanxizi  
       Feb 27, 2023   ❤️ 1
    append 是这样的 里面有个 growslice 扩容机制 memcopy 变成新数组的过程
    1343EFF
        6
    1343EFF  
       Feb 27, 2023
    看着像 php 的风格哈哈哈返回一个新的数组而不是让你引用旧的
    echoless
        7
    echoless  
    OP
       Feb 27, 2023
    @nickchenyx #2 我以为是在原有 arr 的基础上去扩展.

    看来是

    如果原来的 arr 够用, 就直接在上面扩展
    不够就会新创建一个 arr(把数据 copy 过去).
    echoless
        9
    echoless  
    OP
       Feb 27, 2023
    @1343EFF #6 坑在于 如果原来的是容量够, 就是引用旧的. 我觉得每个 golang 程序员都要被咬一次
    echoless
        10
    echoless  
    OP
       Feb 27, 2023
    @beidounanxizi #8 多谢, 普通使用要看原理, 说明设计是不够自然.
    Maboroshii
        11
    Maboroshii  
       Feb 27, 2023
    是这样的啊,要不然就是 array.append 方法了。而且一般写代码如果这样写,看代码的人都要晕了,一会儿旧一会儿新的。。
    cmdOptionKana
        12
    cmdOptionKana  
       Feb 27, 2023   ❤️ 1
    @wuhaoecho 语言怎么设计,有得有失,比如设计成 Java 那样,确实低级坑是少一点,但内存占用就会大。

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

    像 C/C++, Rust 之类,低级坑更多,需要程序员耗费精神自己小心处理的地方更多,但运行效率也更高。
    echoless
        13
    echoless  
    OP
       Feb 27, 2023
    @cmdOptionKana #12 统一你的观点, 所以我觉得 golang 是比 java 更难的语言, 多了一层 pointer, 弄出来很多“似是而非”的问题.
    cmdOptionKana
        14
    cmdOptionKana  
       Feb 27, 2023
    @wuhaoecho 我感觉难度差别很细微,各有各的难点,Java 也有一些很复杂的地方。

    C++, Rust 是难度高得很明显,但如果 Go 和 Java 比,就算说 Go 难,但难那么一点点,几乎可以忽略不计。
    fo0o7hU2tr6v6TCe
        15
    fo0o7hU2tr6v6TCe  
       Feb 27, 2023
    op 真的是边骂边学 golang...
    MoYi123
        16
    MoYi123  
       Feb 27, 2023   ❤️ 1
    @wuhaoecho 不是 go 比 java 多了指针, 而是 java 比 go 少了指针.
    echoless
        17
    echoless  
    OP
       Feb 27, 2023
    @cmdOptionKana #14 我虽然写的 java 不多, 但是不记得有什么困惑, golang 感觉老搞不清. 虽然也能写, 老觉得这样写是不是符合“标准”, java python 这些从来没有这样的困惑. rust c++ 跟 go java 不是一个层次的, 难是预期之内的.
    echoless
        18
    echoless  
    OP
       Feb 27, 2023
    @hzjseasea #15 没办法啊, 生活所迫, 我要是 python 能找到理想的工作才不会学 golang, 不过我把可以骂的点, 都搞清楚了, 就学会了么.
    lesismal
        19
    lesismal  
       Feb 27, 2023
    c 时代的 realloc 就是这样的,只是那些语言为了搬砖效率封装了一大堆、然后圈养了大批 CURDer
    fo0o7hU2tr6v6TCe
        20
    fo0o7hU2tr6v6TCe  
       Feb 27, 2023
    @wuhaoecho 我之前也是 python 转的 go,那时候还偶尔看点 rust ,当时给我的感觉就是卧槽这才是代码,python 太多东西给你封装起来 你写代码的时候压根看不见,现在把这些封装的都抛出来让你自己管理了,就觉得这也不好那也不好了... 像 go 的 map slice map channel 这四块都可以去了解下源码, 反正你找工作也要了解的
    echoless
        21
    echoless  
    OP
       Feb 27, 2023
    @hzjseasea #15 https://www.sunp.eu.org/t/919283#reply22

    看了这个我真是...

    这阵容估计只有 c++ 可以一拼了吧.
    lesismal
        22
    lesismal  
       Feb 27, 2023   ❤️ 1
    @MoYi123
    > 不是 go 比 java 多了指针, 而是 java 比 go 少了指针.

    这话说的妙极了
    echoless
        23
    echoless  
    OP
       Feb 27, 2023
    @hzjseasea #20 大佬你适合去搞汇编
    echoless
        24
    echoless  
    OP
       Feb 27, 2023
    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
        25
    Nazz  
       Feb 27, 2023 via Android
    设计成 OOP 风格明显会更好,之所以没有大概是因为泛型
    hsfzxjy
        26
    hsfzxjy  
       Feb 27, 2023 via Android
    学过 c 的就感觉很自然,类似 realloc 的行为
    echoless
        27
    echoless  
    OP
       Feb 27, 2023 via Android
    @lesismal less is more go 语言的爹经常说的
    leonshaw
        28
    leonshaw  
       Feb 27, 2023
    像 rust 的 ownership 一样,自己制定一些规则,例如只能通过一个 owner slice append ,append 以后其它相关 slice 都失效。
    zagfai
        29
    zagfai  
       Feb 27, 2023
    @lesismal 为什么觉得是圈养了 curder 而不是技术发展提高了生产力了?现在没人钻木取火了吧?
    lanlanye
        30
    lanlanye  
       Feb 27, 2023
    因为 slice 底下是固定大小的数组,不够了要扩容+copy ,你可以试试用 make 来指定底层数组的大小,只要不超过这个大小就不会出现问题。
    但归根结底,不知道这个就容易踩坑。
    lesismal
        31
    lesismal  
       Feb 27, 2023
    @wuhaoecho
    go 爹说的没毛病,我的这个 id (les is mal)也是 less is more 缩写拼接变换得到的
    很多人嘲讽 go 大道至简,殊不知是他们习惯了搬砖的工作、而 go 不是只为了简单搬砖。。。
    lesismal
        32
    lesismal  
       Feb 27, 2023
    先走出自己的舒适区,然后不知不觉就破境了
    lesismal
        33
    lesismal  
       Feb 27, 2023
    @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
        34
    lesismal  
       Feb 27, 2023
    @zagfai
    go rust 或者 c/cpp ,不是钻木取火。
    如果这些是钻木取火,未来 AI 写代码成熟了,那时候的人同样也会说用 java php 这些是钻木取火、谁还自己写代码啊!?

    过去这十几年,IT 这条线发展太快了,不知道 AI 迭代的速度会有多快,有生之年是否能见识到机器生命雏形甚至更高阶一点:joy:
    pkoukk
        35
    pkoukk  
       Feb 27, 2023   ❤️ 1
    不扩容之前,slice 指向底层的 array 不会变,扩容之后就变了
    所以不建议 x := [3]string{"A", "B", "С"}这么用
    一开始就 x:=[]string{},之后 append 也是 x=append(x,...)
    echoless
        36
    echoless  
    OP
       Feb 28, 2023
    @pkoukk #35 https://go.dev/play/p/tMshcyKhLSU 用 x := []string{"A", "B", "С"} 结果是一样的.
    pkoukk
        37
    pkoukk  
       Feb 28, 2023
    @echoless 你别光看前半句不看后半句啊....
    echoless
        38
    echoless  
    OP
       Feb 28, 2023
    @pkoukk #37 哈哈 你的观点楼上有人提过, 就是要最佳实践, 其实就是把负担留给程序员.

    问题是这玩意可是面试官, 考试最喜欢的.

    反正这个 append 我的坑 我是踩过了.
    zagfai
        39
    zagfai  
       Feb 28, 2023   ❤️ 1
    @lesismal 别误会。。我不是说 java 很好,我不仅说 go 是钻木取火,java ,rust 也是。连无穷整型都不是 builtin 的,都是比胶水 python 低一个层次的抽象。
    性能和开发效率的极致得占一个吧~而不是像 go
    echoless
        40
    echoless  
    OP
       Feb 28, 2023
    @zagfai #39 现在这些语言就是 features 取舍的组合, go 我觉得就是宣传过头, 做一些 infra 的工具还行. 大公司做一些高并发啥的也可以理解, 小公司跟风上 go 去写 crud 感觉是无法理解的(动不动 BAT 谁谁都用了, nnd 是处理一样的问题么).
    echoless
        41
    echoless  
    OP
       Feb 28, 2023
    哪天 chatgpt, copilot 能写代码的时候, 估计又有高级程序员跳出来说, xxx 圈养了一堆 crud 都不懂, 只会 prompt 的 XX.
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   2916 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 74ms · UTC 06:34 · PVG 14:34 · LAX 23:34 · JFK 02:34
    ♥ Do have faith in what you're doing.