2 回答

TA貢獻1895條經驗 獲得超3個贊
鑒于 Go 是垃圾收集的并且不允許指針算術,因此您可以做錯的事情并不多。您可以unsafe
為此使用包,但它的名稱不言而喻 - 它是不安全的。
nil
指針還在。取消引用它們會導致恐慌,這有點像 C#/Java 中的異?!銜玫揭粋€清晰的錯誤描述和它發生的堆棧跟蹤。
內存泄漏 - GC 幾乎可以為您做所有事情,就像在 C#/Java 中一樣。但是我知道有一個特殊情況 - 切片。刪除一個元素通常是通過像這樣創建另一個切片來完成的:
a = append(a[:i], a[i+1:]...)
此代碼可能會泄漏您刪除的元素。那是因為在內部 slice 是一個包含數組(只是一個指針)、長度和容量的結構體。當您刪除一個元素時,新切片可能包含相同的數組,它仍然會引用您刪除的元素。GC 不會釋放它。要解決這個問題,您需要在刪除元素之前將其歸零。
并且還有指針與值方法接收器的混淆。這不是錯誤,更像是您必須做出和理解的設計決策。帶有值接收器的方法將獲得接收器的副本,它不能修改狀態。所以如果你想修改狀態,那么你需要指針接收器。此外,如果您的結構很大并且您不希望每次調用方法時都復制它們,您可能還想使用指針接收器。

TA貢獻1998條經驗 獲得超6個贊
我發現的常見錯誤是人們忘記了復雜結構中的指針。
每個 slice、map、interface 都是一個指針。當您有一個包含另一個包含指針的結構的結構時,您可能會看到S1{s2: S2},并且您認為這樣復制結構很好:a=b當實際上它不好時,如在 s2 內部,一個指針變量,比方說p,會有他們的地址被復制,而不是它指向的值。當 yoy 修改在 *a.s2.p 處找到的值時,*b.s2.p 將返回相同的值。
package main
import (
"fmt"
)
type S1 struct {
v int
s2 S2
}
type S2 struct {
p *int
}
func main() {
x := 1
b := S1{v: 10, s2: S2{p: &x}}
a := b
fmt.Printf("a = %+v\nb = %+v\n*a.s2.p = %d\n*b.s2.p = %d\na.s2.p = %p\nb.s2.p = %p\n", a, b, *a.s2.p, *b.s2.p, a.s2.p, b.s2.p)
*a.s2.p = 5
fmt.Printf("*a.s2.p = %d\n*b.s2.p = %d\na.s2.p = %p\nb.s2.p = %p\n", *a.s2.p, *b.s2.p, a.s2.p, b.s2.p)
}
http://play.golang.org/p/KQ99KICgbu
這是一個非常簡單的示例,看起來很明顯存在問題,但在更大的應用程序中,這可能不那么明顯。
頻道也會出現此問題。如果您發送一個指針,您將在另一端獲得相同的指針(指針值的副本,這是一個地址)。在這種情況下,與第一種情況一樣,安全的解決方案是使用 Clone 函數來創建克隆對象。您通過您的頻道發送克隆,并且不再在發送方使用它。
- 2 回答
- 0 關注
- 216 瀏覽
添加回答
舉報