go slice 切片的一个疑问 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
yujianwjj
V2EX    Go 编程语言

go slice 切片的一个疑问

  •  
  •   yujianwjj 2024-01-12 17:09:58 +08:00 1880 次点击
    这是一个创建于 708 天前的主题,其中的信息可能已经有所发展或是发生改变。

    代码里面看到一个 reset 函数,函数里面有个下面的语句,t.a 是个 slice 类型

    t.a = t.a[:0] 

    这个写法跟 t.a = nil 有啥区别吗?

    13 条回复    2024-01-15 17:42:15 +08:00
    DefoliationM
        1
    DefoliationM  
       2024-01-12 17:10:58 +08:00
    t.a[:0] 后面 append 的时候会复用底层已经申请的内存
    Frankcox
        2
    Frankcox  
       2024-01-12 17:12:17 +08:00
    a[:0]是一个长度为 0 的切片吧
    bruce0
        3
    bruce0  
       2024-01-12 17:13:00 +08:00
    `t.a = t.a[:0]` 底层的数组没有释放, 只是 把 切片的当前 len 设置成了 0

    `t.a = nil` 直接把当前的切片设置成空了,底层的数据和当前切片分开了, runtime 可以把 底层的数组回收了
    muntoya
        4
    muntoya  
       2024-01-12 17:14:15 +08:00
    t.a[:0]只是把长度清零,nil 是把整个对象清零了
    Jony4Fun
        5
    Jony4Fun  
       2024-01-12 17:14:53 +08:00
    t.a = t.a[:0]
    相当于把 slice 结构里的 len 改为 0 了,cap 保持不变。跟 #1 说得一样,append 的时候,在数量<=cap 时,就不会触发 grow 了。

    t.a = nil
    原来底层数组可能就要被回收了。
    thinkershare
        6
    thinkershare  
       2024-01-12 17:44:19 +08:00
    go 中很多基本的值类型都不是纯粹的值(凡是存储了指针成员的值类型都是如此)。
    这导致在 Go 中很多时候需要思考指针,会造成一定的心智负担,复制一个带有指针的值类型对象会导致新值和原来的值底层能够同时访问访问指针指向的对象。
    slice 的切片操作本质上是共享了底层的指针成员,然后修改了长度字段,我个人是不喜欢这种设计的(算是为了性能做的妥协).
    如果值类型是不可变类型(即它的全部字段成员在初始化后就不再可变),那这种心智负担就会降低(string 类型就是如此)。
    mainjzb
        7
    mainjzb  
       2024-01-12 18:02:36 +08:00   2
    实在不敢同意楼上这大哥在胡言乱语什么鸟东西
    RoccoShi
        8
    RoccoShi  
       2024-01-12 18:04:09 +08:00
    实在不敢同意楼上这大哥在胡言乱语什么鸟东西
    mainjzb
        9
    mainjzb  
       2024-01-12 18:51:11 +08:00
    为了防止被人说我乱喷。。我回一下吧。
    你所说的所有东西都和指针没有关系。
    首先楼主的问题就和指针八竿子打不着,更别说指针封装在 silce 里面根本不让你外部调用。楼主的问题只有一个原因,go 没有给一个 clean()函数的语法糖,让没有太多经验的人对这行代码摸不着头脑,而这帮 C 语言过来的人却习惯了这样的不直观表达方式作为解决方案。
    你说的 slice copy 浅拷贝的问题。这没有指针的 java 也有这问题。这和指针也没有关系。所以你还需要一个 b := slice.clone() 的语法糖。
    但是你不想要这个,你想要的是比 rust 交出所有权更先进的=即是 deep copy 。在各大语言还在努力用引用解决性能问题的时候,我们做到了人人平等,每个变量都拥有平等公开的享用硬件的权力。
    如果值类型是不可变类型,心智负担会下降,我一直时间无法想象如何写插入和排序功能。突然又想起我刚入行遇到的老师傅对我说的话,管他呢,先 new 10M 内存。
    slowman
        10
    slowman  
       2024-01-12 19:00:28 +08:00
    这种技巧不应该封装成函数
    go 做的那么精简, 不是为了方便添油加醋
    如果连 go 的基本数据结构都不愿意看, 就不要写 go, 也不要问
    rekulas
        11
    rekulas  
       2024-01-12 21:16:20 +08:00
    Marshal 一下你就能看出区别了 一个是[]一个是 null
    说明 0 长度切片跟空对象的区别
    iseki
        12
    iseki  
       2024-01-13 15:57:56 +08:00 via Android
    我觉得 #6 说的没太大毛病,就是说的太绕,不熟悉的人难以理解。Go 的 slice 设计本来就是个大坑,是缺乏思考或者说设计上懒惰的直接体现。append 操作返回值的模糊性导致相当场合 append 只有 x=append(x, blah) 这一个用法。
    thinkershare
        13
    thinkershare  
       2024-01-15 17:42:15 +08:00
    @iseki 懒得和看不懂的人解释,go 选择在栈上常用的值类型中存储指针这种设计,并将其用在了内置的几大核心类型中,这个设计对于任何不是从 C 语言学过来的人理解其行为都是晦涩的,虽然是为了降低 GC 的负担,但我不认为这个设计是值得,这个设计导致 go 中很多基础的 API 看上去就非常丑陋,你说的 x=append(x, blah) 只是一个典型案例。go 的 goroutine 和接口组合都是很好的设计,降低了心智负担。但 slice 的底层模式导致的指针的无孔不入,对于我这个写惯了 js/java/c#/python 的人来说,是非常不喜欢的,明显破坏了编程语言的简洁和清晰度。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     982 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 18:31 PVG 02:31 LAX 10:31 JFK 13:31
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86