Golang 里面选择 []T 还是 []*T?

2020-04-21 13:23:58 +08:00
 wangbenjun5

我看到公司项目里面无论是方法参数还是返回值全部都是*T,也就是都是指针

根据很多文章介绍,Go 里面只存在值传递,但是如果作为函数返回值来用,加个指针意义何在?

func something()([]*T) {

}

经过我测试,加上指针后内存分配的次数反而多了,性能有所下降

5548 次点击
所在节点    程序员
33 条回复
LANB0
2020-04-21 15:07:13 +08:00
大结构体用指针还可以防止堆栈溢出吧? C 系程序员乱入
wangbenjun5
2020-04-21 15:10:32 +08:00
@simenet
@keepeye
@fanhed

哈哈,各位老哥是认真的吗?
sonxzjw
2020-04-21 15:18:03 +08:00
楼主得出内存分配次数更多,性能下降,这个我确实有点疑惑。

之所以返回指针,也是跟值复制有关的。如果是返回 []T,则函数内会有一个 []T,然后再复制一个 []T 作为返回赋值给调用函数的地方。此时,就有 2 份 []T 了。

如果返回 []*T 呢?同样也是有 2 份 []*T 的,但此时的 2 份,只是 2 份“引用”而已,嗯...2 份“内存地址”和一份真正存了值的内存。怎么看内存的占用都比 2 份完整的 []T 所占用的内存要小吧

这是我的回答,如有错误,欢迎指教
justin2018
2020-04-21 15:35:04 +08:00
一般看 IDE 提示 有问题我就改 😢

没问题我就用*T 面向 IDE 编程 小白一个 还在摸索~
wangbenjun5
2020-04-21 15:39:57 +08:00
@sonxzjw 我不知道是不是因为我测试不严谨,我写了 2 个方法,各返回 100 个 T,一个返回[]T, 一个返回[]*T

使用 Go 自带 bench 测试,带上了 benchmem,得出的 ns/op 、allocs/op 结果带指针的都大一点,但是 B/op 小一点
Muninn
2020-04-21 16:00:47 +08:00
我是主要看这个 slice 的使用情况。 如果要 for range 使用,并且这个 *T 作为 receiver 有方法,那就用 []*T,更方便点。 其他情况都用 []T 。
lewinlan
2020-04-21 20:39:08 +08:00
数组总是要遍历的。
一般来说无脑*T 就可以了。
把这精神省下来去思考逻辑和架构吧。
mornlight
2020-04-21 21:04:26 +08:00
@sonxzjw #23 这个理解不对,不管 []T 还是 []*T,都是 slice,返回出去的时候都有一次「拷贝」,只是 slice 的拷贝成本非常低。slice 本质上是这么个东西:
type slice struct {
array unsafe.Pointer
len int
cap int
}

这里的区别是往 []T 填充元素的时候,如果 T 结构体很大,那么使用指针能减少拷贝值的体积。
monkeyWie
2020-04-22 08:55:12 +08:00
看标准库源码里一般返回的是[]*T
wweir
2020-04-22 09:54:08 +08:00
2,除非明确这玩意要拷贝
index90
2020-04-22 10:11:13 +08:00
[]*T 有个好处,就是 for range 的时候,可以直接修改里面的元素,而不需要用下标去修改。

个人觉得没有性能上的差别,更应该站在语义上考虑,一般情况下用[]*T,如果你不想元素被修改(语义上)用[]T
vlrog
2020-04-22 15:06:31 +08:00
围观大佬们讨论
wangbenjun5
2020-09-23 12:16:44 +08:00
@index90 说得好

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/664610

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX