Go 我不明白什么时候在路上使用指针

Go 我不明白什么时候在路上使用指针,go,Go,我正在参观围棋语言,我有一个关于指针的问题 示例代码: 包干管 进口 fmt 时间 类型MyError结构{ 时间到了,时间到了 什么弦 } func e*MyError错误字符串{ 返回fmt.FAT%v,%s, e、 什么时候,什么 } func运行错误{ 返回和MyError{ 时间到了,现在, 它不起作用, } } func main{ 如果错误:=run;错误!=nil{ 打印错误 } } 在本例中,它使用*MyError和&MyError,但我尝试删除*and&并且它工作正常。为什么

我正在参观围棋语言,我有一个关于指针的问题

示例代码:

包干管 进口 fmt 时间 类型MyError结构{ 时间到了,时间到了 什么弦 } func e*MyError错误字符串{ 返回fmt.FAT%v,%s, e、 什么时候,什么 } func运行错误{ 返回和MyError{ 时间到了,现在, 它不起作用, } } func main{ 如果错误:=run;错误!=nil{ 打印错误 } }
在本例中,它使用*MyError和&MyError,但我尝试删除*and&并且它工作正常。为什么他们在这个例子中使用指针?与正态变量有什么区别?什么时候应该使用指针?什么时候应该使用指针?这是一个非常大的问题,没有简单的答案。指针是一种传递对值(而不是值本身)的引用的方法,允许您修改原始值或查看对该值的修改。它还可以防止复制,这在非常有限的情况下可能是一种性能改进。不要一直传递指针,因为这可能是一种性能改进。最后,指针还可以表示虚无,每个指针都可以为零。这既是福也是祸,因为在访问它之前,您必须检查每个指针是否为零

在您的特定示例中,返回&MyError有效的原因是,您的Error函数对指向MyError的指针*MyError的值进行操作,而不是对MyError本身的值进行操作。这意味着*MyError实现了错误接口,因此可以分配给错误类型,因此可以从任何期望错误作为返回值的函数返回

返回MyError本身不起作用,因为MyError不是*MyError。Go在处理函数接收器时做了一些有用的事情:如果接收器是*MyError,它将允许您调用MyError或*MyError上的任何方法,但是如果类型是*MyError,它将只允许您调用*MyError上的方法-也就是说,Go不会凭空为您创建指针

如果您要从func e*MyError中删除*,您将告诉Go该错误适用于MyError的任何实例,这意味着*MyError和MyError都将履行该契约。这就是为什么在不使用指针接收器时,以下两项都有效的原因:

func (e MyError) Error() string {}

var _ error = MyError{} // Valid
var _ error = &MyError {}

在这种特殊情况下,使用指针不会有什么不同。这里有一种方式来看待它:

在Go中,所有变量都按值传递。这意味着:

type T struct {...}

func f(value T) {..}

f(t)
在上面,t作为值传递。这意味着当调用f时,编译器创建t的一个副本并将其传递给f。f对该副本所做的任何修改都不会影响用于调用f的t

如果使用指针:

func f(value *T) {...}

f(&t)
上面,编译器将创建一个指向t的指针,并将该指针的副本传递给f。如果f对值进行更改,则这些更改将在用于调用f的t的实例上进行。换言之:

type T struct {
  x int
}

func f(value T) {
   value.x=1
}

func main() {
   t:=T{}
   f(t)
   fmt.Println(t.x)
}
这将打印0,因为f所做的修改是在t的副本上完成的

上面,它将打印1,因为对f的调用更改了t

同样的想法也适用于方法和接收器:

type T struct {
   x int
}

func (t T) f() {
   t.x=1
}

func main() {
   t:=T{}
   t.f()
   fmt.Println(t.x)
}
上面的程序将打印0,因为该方法修改了t的副本

上面的程序将打印1,因为方法的接收器是用指针声明的,调用t.f相当于f&t

因此,如果要修改对象,或者复制对象的成本太高,则在传递参数或声明方法时使用指针

这只是指针参数故事的一小部分

type T struct {
   x int
}

func (t T) f() {
   t.x=1
}

func main() {
   t:=T{}
   t.f()
   fmt.Println(t.x)
}
func (t *T) f() {
   t.x=1
}

func main() {
   t:=T{}
   t.f()
   fmt.Println(t.x)
}