GO 语言的指针使用规范是什么?

2017-11-09 14:51:12 +08:00
 zjsxwc

在定义 struct 的 method 时, 好像这这两种方式没有区别:


func (st StructType) MyMethod1() {}

func (st *StructType) MyMethod2() {}

而且调用访问时好像, 也没区别:


st := StructType{}
st.MyMethod1()
st.MyMethod2() 

于是我就困惑了, 我看了 github 上主流的几个项目, 好像都倾向于使用MyMethod2这种接收者为指针类型的定义方式, 很少见到MyMethod1的方式, 这里有什么规范吗?

3387 次点击
所在节点    程序员
7 条回复
rrfeng
2017-11-09 14:56:12 +08:00
boboliu
2017-11-09 15:02:53 +08:00
为什么不试试 st := &StructType{} 呢?
cloudzhou
2017-11-09 15:03:55 +08:00
传参,指针和结构体的区别,即使传递指针,对指针来说,也是创建一个变量把指针复制过去。

st := StructType{}
st.MyMethod1()
st.MyMethod2()

st.MyMethod2() 等同于 (&st).MyMethod2() ,是编译器给你做了
------
st := &StructType{}
st.MyMethod1()
st.MyMethod2()

如果这样,你会发现编译不过去,因为 MyMethod1 并不是指针类型方法
------
func (st StructType) MyMethod1() {} 等同于 func MyMethod1(st StructType) {}
func (st *StructType) MyMethod2() {} 等同于 func MyMethod2(st *StructType) {}

如果传递结构体,会产生一个结构体的复制,而指针,只是指针变量的复制。
如果在里面有赋值操作:
func (st StructType) MyMethod1() { st.Name = "name" }
func (st *StructType) MyMethod2() { st.Name = "name" }

MyMethod1 不会修改 st 本身;而 MyMethod2 会
这是所谓的 “副作用”

如何选择:
------
绝大部分时间,选择指针方法。
对于小对象,只读对象,可以选择结构体方法。典型的比如 time.Time
georgetso
2017-11-09 15:04:11 +08:00
还有一个区别:

The method set of any other named type T consists of all methods with receiver type T. The method set of the corresponding pointer type *T is the set of all methods with receiver *T or T (that is, it also contains the method set of T).
qianguozheng
2017-11-09 15:16:07 +08:00
Good.
SuperMild
2017-11-09 15:58:36 +08:00
把这个看明白,Go 里的指针就完全理解了
https://blog.golang.org/laws-of-reflection
motopig
2017-11-09 16:47:53 +08:00
```
package main

import "fmt"

type StructType struct {
StructChildOne
*StructChildTwo
}

type StructChildOne struct{}
type StructChildTwo struct{}

func (sto StructChildOne) One() {
fmt.Println("child one method")
}

func (stt *StructChildOne) Towo() {
fmt.Println("child two method sss")
}

func (stt *StructChildTwo) Two() {
fmt.Println("child two method")
}

func (stt StructChildTwo) Twoo() {
fmt.Println("child two method")
}

/*如果在 S 中包含一个嵌入类型 T,那么 S 和*S 的方法集合中都会包含接收者类型为 T 或*T 的所有方法
如果在 S 中包含一个嵌入类型*T,那么 S 和*S 的方法集合中只包含接收者类型为*T 的方法*/

func main() {
var point = new(StructType)
var point2 = StructType{}
point.One()
point.Towo()
point2.One()
point2.Two()
point2.Twoo()// 这行会报错
}
```

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/404963

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX