go语言函数传参可以传递struct,传递pointer,还有传递interface,他们主要区别是什么呢?
package main
import (
"fmt"
"unsafe"
"reflect"
)
type MyInterface interface {
}
type MyStruct struct {
i1 int64
i2 int64
i3 int64
i4 int64
i5 int64
}
func Hello1(p MyStruct) {
fmt.Println("size:", unsafe.Sizeof(p), "; type:", reflect.TypeOf(p), "; value:", reflect.ValueOf(p))
}
func Hello2(p * MyStruct) {
fmt.Println("size:", unsafe.Sizeof(p), "; type:", reflect.TypeOf(p), "; value:", reflect.ValueOf(p))
}
func Hello3(p MyInterface) {
fmt.Println("size:", unsafe.Sizeof(p), "; type:", reflect.TypeOf(p), "; value:", reflect.ValueOf(p))
}
//func Hello4(p * MyInterface) {
// fmt.Println("size:", unsafe.Sizeof(p), "; type:", reflect.TypeOf(p), "; value:", reflect.ValueOf(p))
//}
func main() {
m := MyStruct { 11,22,33,44,55 }
Hello1(m)
Hello2(&m)
Hello3(m)
//Hello4((* MyInterface)(&m))
}
运行结果如下
$ go build main.go && ./main
size: 40 ; type: main.MyStruct ; value: {11 22 33 44 55}
size: 8 ; type: *main.MyStruct ; value: &{11 22 33 44 55}
size: 16 ; type: main.MyStruct ; value: {11 22 33 44 55}
可以看到三个的区别
- 传struct是传值,把原数据做完整拷贝,作为参数传递给callee
- 传pointer,传递的是原数据的一个指针,从而在callee里面如果对原数据做了改动,会反映到caller
- 传interface,传递的是一个interface对象,这个对象占用16字节长度,包含一个指向原数据的指针,和一个指向运行时类型信息的指针。
当然对于指向interface的指针这种用法是几乎没有用到的(例子中的Hello4()函数,编译没有成功,我不知道应该怎么写),也不建议这么用,因为interface本身差不多就是一个指针(其实是两个指针),stackoverflow有一个问答介绍这个问题: https://stackoverflow.com/questions/44370277/type-is-pointer-to-interface-not-interface-confusion
简单的说就是不要有interface指针这种用法。
下面一篇文章来介绍函数如何传递interface.