golang 函数返回值 2 个写法,哪个更好? - V2EX
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 3975 次点击
    这是一个创建于 1560 天前的主题,其中的信息可能已经有所发展或是发生改变。
    自己平时写项目,喜欢把返回值 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  
    PRO
       2021-07-12 18:07:30 +08:00 via iPhone
    第一种,改别人代码时被第二种坑过
    darksword21
        4
    darksword21  
    PRO
       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
    @moty0 但是可能那个 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     Solana     5861 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 37ms UTC 03:22 PVG 11:22 LAX 20:22 JFK 23:22
    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