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

什么时候返回值什么时候返回指针?

  •  
  •   index90 · 2020-04-08 11:15:55 +08:00 · 4448 次点击
    这是一个创建于 1722 天前的主题,其中的信息可能已经有所发展或是发生改变。
    自从了解到“逃逸机制”,写程序时心智负担增加不少。
    平时开发时,是否需要有意识地去考虑内存分配问题?
    还是更专注于语义?有没有这方面的方法论?
    第 1 条附言  ·  2020-04-08 13:20:36 +08:00
    最近记忆力减退

    现在想起当时看到那篇文章讲关于“逃逸机制”,其目的是想指出“传递指针能够提供程序性能”是谣言。(传递指针,并不是毫无副作用,它可能带来 GC 的影响)

    在收藏夹找到另一篇文章,讲述如何设计数据以及语义
    https://www.ardanlabs.com/blog/2017/06/design-philosophy-on-data-and-semantics.html
    24 条回复    2020-05-06 15:28:03 +08:00
    no1xsyzy
        1
    no1xsyzy  
       2020-04-08 11:30:18 +08:00
    这方面的方法论比 go 语言还老得多:
    premature optimization is the root of all evil
    behanga
        2
    behanga  
       2020-04-08 11:57:20 +08:00
    如果是 C++,就用只能指针啊,不怕泄露,随便用。
    behanga
        3
    behanga  
       2020-04-08 11:57:40 +08:00
    只能->智能
    fluorinedog
        4
    fluorinedog  
       2020-04-08 12:07:51 +08:00 via iPhone   ❤️ 2
    gc 语言考虑啥 allocation 问题... 瞎写就是了,先把功能写完,然后再 profiling 优化...
    根据我的经验,真正的热点往往不是你想象的那些,所以提前优化确实是万恶之源。
    kkeiko
        5
    kkeiko  
       2020-04-08 12:34:49 +08:00
    先说什么语言,不同语言虽然语法上看起来都叫指针,但底层原理其实都不太一样,你既然想要在合适的地方使用指针来提高性能,那就要了解所使用语言的底层原理是怎么实现指针的。
    kaedea
        6
    kaedea  
       2020-04-08 13:16:44 +08:00 via Android
    逃逸机制能细讲一下?
    cmdOptionKana
        7
    cmdOptionKana  
       2020-04-08 13:17:34 +08:00
    逃逸机制是指什么?
    index90
        8
    index90  
    OP
       2020-04-08 13:21:41 +08:00   ❤️ 1
    @kaedea
    @cmdOptionKana
    Google Golang Escape Analysis
    yongestcat
        9
    yongestcat  
       2020-04-08 13:43:17 +08:00 via Android
    逃逸机制是啥 求科普
    hst001
        10
    hst001  
       2020-04-08 13:45:38 +08:00
    如果程序不是那种需要注重性能,不要考虑这些。真的需要性能的程序,用什么语言写都一样会增加心智负担。

    简单的说,大对象使用指针,小对象,比如只有几个 int 类型字段,可以使用值拷贝,没有明确的分界线可以区分怎么使用,因为还要考虑到实际对象产生的数量,这点只有实际 profiling 才知道。

    另外 map 类型的 key/value 也是有讲究的,会影响到 gc 。

    不过还是那一句,撸代码的时候不如把时间花在逻辑设计上面,别瞎优化(万一不小心负优化了呢?),跑完再优化。
    pwli
        11
    pwli  
       2020-04-08 13:46:40 +08:00 via Android
    没必要过早优化吧
    pwli
        12
    pwli  
       2020-04-08 13:48:47 +08:00 via Android
    @yongestcat 本来应该是在栈上分配的,一看外部还保留着引用,这种就会逃逸到堆上,这只是一种简单的场景
    useben
        13
    useben  
       2020-04-08 14:04:50 +08:00
    逃逸机制没必要在开发阶段考虑吧, 而且大多数情况也影响不到你的业务吧, 后面有影响直接 pprof 优化就是了
    ppphp
        14
    ppphp  
       2020-04-08 14:28:08 +08:00
    写 go 性能早就不在意了,传指针还是值只看用的函数是不是只读这个对象的,是只读的就传值,有修改就传指针
    zhangchioulin
        15
    zhangchioulin  
       2020-04-08 14:53:39 +08:00
    这方便的讨论很多,列举一个我觉得很棒的:
    https://stackoverflow.com/questions/23542989/pointers-vs-values-in-parameters-and-return-values

    1. Slices, maps, channels, strings, function values, and interface values 内部用指针实现,返回指向它们的指针通常是多余的。
    2. 大型结构体或需要更改返回值情况用指针,否则返回值
    2.1 大型结构体?当你把结构体的 field 拆分开来放到方法中时你觉得参数很多时,那就是“大型结构体”
    Jirajine
        16
    Jirajine  
       2020-04-08 15:06:35 +08:00 via Android
    反正有 GC,你完全没必要去区分堆栈。

    https://golang.org/doc/faq#stack_or_heap

    >How do I know whether a variable is allocated on the heap or the stack? 
    From a correctness standpoint, you don't need to know. Each variable in Go exists as long as there are references to it. The storage location chosen by the implementation is irrelevant to the semantics of the language.

    是否传指针也没必要想太多,基本类型和本身就是引用的传值,其他一律传指针。
    timothyye
        17
    timothyye  
       2020-04-08 15:08:04 +08:00 via Android
    感觉 Rust 的 ownership 机制能规避这些问题
    scnace
        18
    scnace  
       2020-04-08 16:11:53 +08:00 via Android
    前天看了 Go 夜读的内存对齐,也发现之前写的代码或多或少会有点问题(有很多的多余的内存分配),但是我一直觉得这些属于 suggestions 和,真正在这种地方遇到瓶颈的地方的场景很少,至少在平常的业务场景中,把某段业务逻辑设计再精简点,少几次 I/O 操作,优化下算法复杂度,往往产出比花在这些地方要值得。不过,很多常见优化项可以通过配置 IDE/Editor 的 golang ci lint 规则解决就是了
    lewinlan
        19
    lewinlan  
       2020-04-08 16:39:02 +08:00 via Android
    go 故意没有在文档中说堆栈的区别,就是让我们不要去关心堆栈问题。
    同意前排的观点,先实现功能,后期再 profile 优化,别想太多。
    Cloutain
        20
    Cloutain  
       2020-04-08 17:28:41 +08:00
    你看看,我们用易语言的人完全不用担心什么 GC 逃逸机制,指针传递就万事大吉了ε=ε=ε=┏(゜ロ゜;)┛逃
    yuguorui96
        21
    yuguorui96  
       2020-04-09 09:17:08 +08:00
    @timothyye ownership 不是规避这种问题,是强迫你要显式的考虑这种问题。
    对于 Golang 来说完全没必要考虑逃逸分析带来的性能影响,都用 Golang 了这种问题交给 GC 和优化器就完了,要不 golang 的优势何在?
    yangbonis
        22
    yangbonis  
       2020-04-09 13:24:07 +08:00 via iPhone
    语义和内存分配应该不是矛盾的
    TransAM
        23
    TransAM  
       2020-04-24 21:37:12 +08:00 via Android
    方法论就是遵循语言的设计。当然 golang 这种允许你选地方的,就参考其他语言,比如小对象直接赋值,大对象用 new 和指针。

    大量小对象的场景(比如游戏单位)就搞个对象池,避免重复创建回收。

    很多语言没有逃逸分析,还有的语言强制你把对象放堆上(比如 java ),还不是一样写?
    sunshinev
        24
    sunshinev  
       2020-05-06 15:28:03 +08:00
    不希望值拷贝的时候,就用指针呗
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1381 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 17:39 · PVG 01:39 · LAX 09:39 · JFK 12:39
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.