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條經驗 獲得超13個贊
在這種特殊情況下,使用指針不會有任何區別。以下是查看它的一種方式:
在 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 關注
- 94 瀏覽
添加回答
舉報