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

golang 函数返回值 2 个写法,哪个更好?

  •  
  •   wangbenjun5 · 2021-07-12 18:05:07 +08:00 via Android · 3584 次点击
    这是一个创建于 1233 天前的主题,其中的信息可能已经有所发展或是发生改变。
    自己平时写项目,喜欢把返回值 return 回去,比如

    所以一般函数都是 function_name()([]struct, error)这种形式。

    但是我经常也看到很多人喜欢另一种写法,就是把返回值作为参数传进去,最后只 return error,像这样 function_name(result *[]struct) error

    结果都是一样,但是过程不一样,我的那种方式需要在函数里面创建一个 slice,把结果塞进去 return 。但是传参数这种方式,可以直接拿来用,所以理论上第二种方式更高效吗?

    大家喜欢哪种写法?
    第 1 条附言  ·  2021-07-12 18:37:02 +08:00
    经过 v 友提醒,我觉得第二种写法主要还是因为很多语言,比如 c,函数是不支持多返回值,估计是习惯,可能以前写 c 写的多
    31 条回复    2021-07-14 18:55:29 +08:00
    keepeye
        1
    keepeye  
       2021-07-12 18:07:21 +08:00
    大多第一种,第二种像是写 c
    wangbenjun5
        2
    wangbenjun5  
    OP
       2021-07-12 18:07:29 +08:00 via Android
    这种把返回值定义好传到目标函数里面获取结果的写法很常见,貌似写 c 语言的比较喜欢这种写法吧?
    darksword21
        3
    darksword21  
       2021-07-12 18:07:30 +08:00 via iPhone
    第一种,改别人代码时被第二种坑过
    darksword21
        4
    darksword21  
       2021-07-12 18:08:18 +08:00 via iPhone
    看错了抱歉,无视上面⬆️
    morty0
        5
    morty0  
       2021-07-12 18:15:05 +08:00   ❤️ 1
    第二种哪里高效了,slice 不也要在外面创建吗
    wangbenjun5
        6
    wangbenjun5  
    OP
       2021-07-12 18:16:12 +08:00 via Android
    @morty0 但是可能那个 slice 在外面本来就需要创建,所以
    wangbenjun5
        7
    wangbenjun5  
    OP
       2021-07-12 18:16:46 +08:00 via Android
    @keepeye 是的,有这个感觉,我还见过有写 Python 的也是这种写法
    colors
        8
    colors  
       2021-07-12 18:22:33 +08:00
    第二种不可取,很容易出问题,而且没有更高效
    generic
        9
    generic  
       2021-07-12 18:23:16 +08:00
    GC 语言里创建 slice 开销较低,如非必要都用第一种。
    wangbenjun5
        10
    wangbenjun5  
    OP
       2021-07-12 18:26:12 +08:00 via Android
    @generic 不一定是 slice,也可能是对象等其它指针类型
    mainjzb
        11
    mainjzb  
       2021-07-12 18:26:22 +08:00   ❤️ 1
    go 选第一种
    C/C++ 选第二种为了控制生命周期,而且他们只能返回一个值,那必然只能返回 err
    {
    auto X = NewResult();
    GetResult(X);
    DoSomething(X);
    //Delete(X);
    }
    C++讲究谁创建,谁释放, 你创建,我忘了释放,那就傻逼了。GetResult 完全可是是 RPC 或者底层库,或者其他不是我写的代码。
    wangbenjun5
        12
    wangbenjun5  
    OP
       2021-07-12 18:28:42 +08:00 via Android
    @mainjzb 突然想起来了,很多语言函数只能返回一个值,哈哈,原来如此
    chotow
        13
    chotow  
       2021-07-12 18:43:32 +08:00 via iPhone
    看标题还以为比较的是 function_name()([]struct, error) 和 function_name()(ret[]struct, err error) 这两种写法 😑
    pkoukk
        15
    pkoukk  
       2021-07-12 18:54:45 +08:00
    个人一般只有涉及反序列化才会用第二种,类似 json.Unmarshal()这种行为的时候才会通过指针替换原来对象里的值
    wangbenjun5
        16
    wangbenjun5  
    OP
       2021-07-12 19:06:15 +08:00 via Android
    @chotow 你说的第二种也操蛋,我极少用
    zoharSoul
        17
    zoharSoul  
       2021-07-12 19:30:56 +08:00
    函数最好不要有副作用,
    后面看代码很累. 一个对象进去一次就变了跟魔法一样
    generic
        18
    generic  
       2021-07-12 19:47:04 +08:00
    @wangbenjun5 我觉得也一样,除非你预期用户几乎总是会重用一个对象作为输出,或者这就是优化的关键点,否则不值得操这个心。
    bringyou
        19
    bringyou  
       2021-07-12 20:01:37 +08:00
    补充一条,因为 go 没有泛型,在一些场合下,第一种调用方还需要来一次类型强转,第二种不用
    ylsc633
        20
    ylsc633  
       2021-07-12 20:26:53 +08:00
    引用类型的 是可以这么用

    但是不建议这样用, 因为你不知道在什么地方改了它, 然后在另外一个地方用了它

    所以我一般都是第一种

    另外,多个返回值真的非常好用

    还有结构体 可以在一个文件里 定义多个实在是太爽了
    k9982874
        21
    k9982874  
       2021-07-12 20:30:41 +08:00 via Android
    第一种,第二种如果没有吃透指针很容易火葬场
    githubhaoliu
        22
    githubhaoliu  
       2021-07-12 21:05:43 +08:00
    修改了就要返回新值,第二种容易出 bug.
    sunmoon1983
        23
    sunmoon1983  
       2021-07-12 21:31:53 +08:00
    从来不用第二种,都是第一种
    janxin
        24
    janxin  
       2021-07-12 22:03:00 +08:00
    你们不用第二种怎么设计 Decode 、Unmarshal 之类的场景的...

    不过一般来说看情况,第一种比较简单,但不是所有的问题都用第一种都能解决
    streamrx
        25
    streamrx  
       2021-07-13 02:53:59 +08:00 via iPhone
    第一种
    sxfscool
        26
    sxfscool  
       2021-07-13 09:17:12 +08:00
    多返回值不香么,为啥还要用没有多返回值语言的方式
    cyrivlclth
        27
    cyrivlclth  
       2021-07-13 09:32:06 +08:00
    一般用第一种吧,第二种多见 Decode Unmarshal 或者 各种库,传的是 interface{},因为不知道你想转换成什么类型所以需要传进去
    dazui
        28
    dazui  
       2021-07-13 10:47:51 +08:00
    传指针这个语法既然有,也不是不能用,可以尽量避免在没有必要时使用,在对象创建和复制开销没有压力的情况下,依赖 GC 是很好的方案。但如果性能存在压力时,通过传指针来尽量减少对象的复制与创建,是可行的优化方案。
    jingslunt
        29
    jingslunt  
       2021-07-13 15:15:38 +08:00
    @bringyou 泛型有了

    type Num interface {}
    func min[T Num](a, b T) T{}
    index90
        30
    index90  
       2021-07-14 10:32:07 +08:00
    accept interface, return struct
    liberize
        31
    liberize  
       2021-07-14 18:55:29 +08:00 via Android
    偏向第二种,很多时候比较简洁
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3269 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 00:39 · PVG 08:39 · LAX 16:39 · JFK 19:39
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.