参数和返回值里面到底用指针还是value

Go里面有很多方式返回一个struct的值或者slice,我们经常会看到的是如下的代码:

type MyStruct struct {
    Val int
}

func myfunc() MyStruct {
    return MyStruct{Val: 1}
}

func myfunc() *MyStruct {
    return &MyStruct{}
}

func myfunc(s *MyStruct) {
    s.Val = 1
}

我知道这三种方式的不同点,第一个返回一个struct的copy,第二个在函数内部创建一个指向struct的指针然后返回,第三个是传入一个已经存在的struct,然后修改他的值。

我在很多源码里面见过这三种不同的用法,我是想知道这个的最佳实践是什么?什么时候应该用哪一种?例如第一种用在一些小的struct(因为这个花费是最小的),第二种应用在大的struct,而第三种可能就是为了非常的节约内存,因为你在不同的调用中重用struct。

slice的例子也是类似如下:

func myfunc() []MyStruct {
    return []MyStruct{ MyStruct{Val: 1} }
}

func myfunc() []*MyStruct {
    return []MyStruct{ &MyStruct{Val: 1} }
}

func myfunc(s *[]MyStruct) {
    *s = []MyStruct{ MyStruct{Val: 1} }
}
已邀请:

mintzhao - 区块链开发者

赞同来自:

这个没什么最佳实践的区别吧。一是看业务需求,二看个人喜好。没有什么特殊情况,我钟爱第二种

liyongjing

赞同来自:

从设计角度是控制权的问题。值:控制权在自己手中,引用:控制权交给了别人。

hubery

赞同来自:

编译器会有优化,把优化关了结果就不一样了

astaxie - 创造、获取、分享、传播和应用Go

赞同来自:

lichao2018

赞同来自:

函数返回值要通过参数返回或者方法要修改对象、拷贝成本较大(比如大结构传值)时 用指针类型。

从汇编角度看,参数和返回值比较大时 指针类型只有一次压栈而值类型会有多次压栈。其实对性能影响很小。

另外,返回指针类型会造成逃逸,可能会造成不必要的堆内存分配。

要回复问题请先登录注册