2 回答
TA贡献1878条经验 获得超4个赞
“我什么时候应该使用指针?”是一个非常大的问题,没有一个简单的答案。指针是一种传递对值(而不是值本身)的引用的方法,允许您修改原始值或“查看”对该值的修改。它还可以防止复制,在非常有限的情况下,复制可能是性能改进(不要一直传递指针,因为它可能是性能改进)。最后,指针还允许您表示“虚无”,每个指针都可以是 。这既是祝福也是诅咒,因为您必须在访问每个指针之前检查它是否是。nil
nil
在您的具体示例中,返回工作的原因是因为您的函数对值(指向 )而不是对自身的值进行操作。这意味着 实现接口,因此可以分配给类型,因此可以从任何期望将 a 作为返回值的函数返回。&MyError
Error()
*MyError
MyError
MyError
*MyError
Error
error
error
返回本身不起作用,因为不是.Go在处理函数接收器时做了一些有用的事情:它会允许你在a上调用任何方法,或者如果接收器是,但它只允许你在a上调用方法,如果类型是 - 也就是说,Go不会凭空为你“创建”指针。MyError
MyError
*MyError
MyError
*MyError
*MyError
*MyError
*MyError
如果您要从 中删除 ,您将告诉 Go 适用于 的任何实例,这意味着两者都将履行该协定。这就是为什么当您不使用指针接收器时,以下两者都有效的原因:*
func (e* MyError)
Error()
MyError
*MyError
MyError
func (e MyError) Error() string {}
var _ error = MyError{} // Valid
var _ error = &MyError {}
TA贡献1842条经验 获得超12个赞
在这种特殊情况下,使用指针不会有任何区别。以下是查看它的一种方式:
在 Go 中,所有变量都按值传递。这意味着:
type T struct {...}
func f(value T) {..}
f(t)
上面,作为值传递。这意味着当调用时,编译器会创建的副本并将其传递给 。对该副本所做的任何修改都不会影响用于调用 。tftfftf
如果使用指针:
func f(value *T) {...}
f(&t)
在上面,编译器将创建一个指向 的指针,并将其副本传递给 。如果对 进行更改,则这些更改将在 used to call 的实例上进行。换句话说:tffvaluetf
type T struct {
x int
}
func f(value T) {
value.x=1
}
func main() {
t:=T{}
f(t)
fmt.Println(t.x)
}
这将打印 0,因为 所做的修改是在 的副本上完成的。ft
func f(value *T) {
value.x=1
}
func main() {
t:=T{}
f(&t)
fmt.Println(t.x)
}
上面,它会打印1,因为调用会改变。ft
同样的想法也适用于方法和接收器:
type T struct {
x int
}
func (t T) f() {
t.x=1
}
func main() {
t:=T{}
t.f()
fmt.Println(t.x)
}
上述程序将打印 0,因为该方法修改了 的副本。t
func (t *T) f() {
t.x=1
}
func main() {
t:=T{}
t.f()
fmt.Println(t.x)
}
上面的程序将打印 1,因为该方法的接收器是用指针声明的,而调用等效于 。t.f()f(&t)
因此,在传递参数时使用指针,或者在声明方法时,如果要修改对象,或者如果复制对象的成本太高,请使用指针。
这只是关于指针参数的故事的一小部分。
- 2 回答
- 0 关注
- 74 浏览
添加回答
举报