跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • Golang 里面选择 []T 还是 []*T?
未分類
14 5 月 2020

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

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

資深大佬 : wangbenjun5 19

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

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

func something()([]*T) {  } 

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

大佬有話說 (32)

  • 資深大佬 : leoleoasd

    大结构体防止拷贝?

  • 資深大佬 : Wirbelwind

    golang 不是 gc 语言吗 难道不是引用语义?

  • 資深大佬 : maichael

    https://www.reddit.com/r/golang/comments/5lheyg/returning_t_vs_t/

    https://github.com/google/go-github/issues/180

  • 資深大佬 : unixeno

    大结构体用指针能减少内存拷贝的时间

  • 資深大佬 : maichael

    我的看法是取决于你的用途。

  • 主 資深大佬 : wangbenjun5

    @maichael 看了链接里面,最终好像也没什么结论,如果按很多文章的说法,那不如统一都加指针,毕竟指针比非指针“多”一些用途

  • 資深大佬 : keepeye

    一直用[]*T 无论 T 多大

  • 資深大佬 : boboliu

    你们都不用 interface 么

  • 資深大佬 : fanhed

    一般来说, 无脑用*T 就好了

  • 資深大佬 : warlock

    复杂结构用指针可以减少拷贝 简单结构不用指针可以提升 GC 性能

  • 資深大佬 : matrix67

    之前印象笔记收藏的:

    我们通过一些代码示例来演示了在 Go 中值类型和指针类型的一些具体表现,最后我们要回答这么几个问题,希望你能够在使用 Go 编程的过程中更加清晰的掌握这些技巧。Receiver Type 为什么推荐使用指针?

    * 推荐在实例方法上使用指针(前提是这个类型不是一个自定义的 map 、slice 等引用类型)
    * 当结构体较大的时候使用指针会更高效
    * 如果要修改结构内部的数据或状态必须使用指针
    * 当结构类型包含 sync.Mutex 或者同步这种字段时,必须使用指针以避免成员拷贝
    * 如果你不知道该不该使用指针,使用指针!

    “结构较大” 到底多大才算大可能需要自己或团队衡量,如超过 5 个字段或者根据结构体内占用来计算。方法参数该使用什么类型?
    * map 、slice 等类型不需要使用指针(自带 buf )
    * 指针可以避免内存拷贝,结构大的时候不要使用值类型
    * 值类型和指针类型在方法内部都会产生一份拷贝,指向不同
    * 小数据类型如 bool 、int 等没必要使用指针传递
    * 初始化一个新类型时(像 NewEngine() *Engine )使用指针
    * 变量的生命周期越长则使用指针,否则使用值类型

    – 不用指针是值传递,基本就不会走 gc,缺点是导致整个 struct 发生内存拷贝,当然被编译器识别为 inline 函数就什么都不会发生,快得一匹。当你函数输入 /返回参数,struct 就几个 int,float,值传递吧!

    – 指针就是类似引用传递,出作用域会走 gc,当然也不是绝对,比如 inline 函数返回指针就不一定会导致堆分配,当然内置的 new 和 make,map,slice 等本身就分配在堆上就必然走 gc 。

    – gc 对于密集型计算服务的后果就是大量 cpu 计算都消耗在 gc 上,严重影响性能,另外栈内存的分配花销时间可能比堆好

    – 其实在 Go 中,除了方法属主参数,指针使用的并不普遍,使用指针参数的主要目的是在函数内能够更改此指针所引用的值。指针有时候也用来避免较大的值赋值代价。比如将一个指针包裹在接口值中的代价比将一个非接口值包裹到接口值中的代价小得多。另一方面,过多的指针会影响垃圾回收的时长,一般这种情况发生在一个容器中含有大量包含指针的元素。

  • 資深大佬 : lhx2008

    主的例子,你测试的值传递传递是切片,又不是传数组,所以数组根本没被复制。。。和你用不用内部指针就更没关系

  • 資深大佬 : ethego

    slice 里本来就是指针,你这样写传的是指针的指针。

  • 資深大佬 : lhx2008

    要说也是 append 进切片的时候会有一次复制,如果你是指针的话复制的东西比较少,但是后面再用的时候都是复制的是切片了。。

  • 資深大佬 : ethego

    自己用逃逸分析看看就知道了

  • 資深大佬 : whahuzhihao

    其实传参时用非指针的 T,能提高 GC 效率

  • 資深大佬 : CEBBCAT

    slice 是两级结构,一层是切片的描述如容量和长度及数组的指针,下层是被上层指向的数组。这样的区别可能是减低数组扩容复制时的时间开销吧,另外这样可能也有一点点加速垃圾回收的考虑?

    我是新手(上海及南方求 Go 坑位)

  • 資深大佬 : ethego

    @lhx2008 只要有 append 进 slice 的操作,被操作实例几乎必逃逸,所以复制也只是复制的指针而已

  • 資深大佬 : zdt3476

    无脑用指针,等需要优化的时候再改就好了。

  • 資深大佬 : simenet

    别问 问就是无脑 *T

  • 資深大佬 : LANB0

    大结构体用指针还可以防止堆栈溢出吧? C 系程序员乱入

  • 主 資深大佬 : wangbenjun5

    @simenet
    @keepeye
    @fanhed

    哈哈,各位老哥是认真的吗?

  • 資深大佬 : sonxzjw

    主得出内存分配次数更多,性能下降,这个我确实有点疑惑。

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

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

    这是我的回答,如有错误,欢迎指教

  • 資深大佬 : justin2018

    一般看 IDE 提示 有问题我就改

  • 主 資深大佬 : wangbenjun5

    @sonxzjw 我不知道是不是因为我测试不严谨,我写了 2 个方法,各返回 100 个 T,一个返回[]T, 一个返回[]*T

    使用 Go 自带 bench 测试,带上了 benchmem,得出的 ns/op 、allocs/op 结果带指针的都大一点,但是 B/op 小一点

  • 資深大佬 : Muninn

    我是主要看这个 slice 的使用情况。 如果要 for range 使用,并且这个 *T 作为 receiver 有方法,那就用 []*T,更方便点。 其他情况都用 []T 。

  • 資深大佬 : lewinlan

    数组总是要遍历的。
    一般来说无脑*T 就可以了。
    把这精神省下来去思考逻辑和架构吧。

  • 資深大佬 : mornlight

    @sonxzjw #23 这个理解不对,不管 []T 还是 []*T,都是 slice,返回出去的时候都有一次「拷贝」,只是 slice 的拷贝成本非常低。slice 本质上是这么个东西:
    type slice struct {
    array unsafe.Pointer
    len int
    cap int
    }

    这里的区别是往 []T 填充元素的时候,如果 T 结构体很大,那么使用指针能减少拷贝值的体积。

  • 資深大佬 : monkeyWie

    看标准库源码里一般返回的是[]*T

  • 資深大佬 : wweir

    2,除非明确这玩意要拷贝

  • 資深大佬 : index90

    []*T 有个好处,就是 for range 的时候,可以直接修改里面的元素,而不需要用下标去修改。

    个人觉得没有性能上的差别,更应该站在语义上考虑,一般情况下用[]*T,如果你不想元素被修改(语义上)用[]T

  • 資深大佬 : vlrog

    围观大佬们讨论

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具