製作結構副本
可以使用賦值簡單地複製結構。
type T struct {
I int
S string
}
// initialize a struct
t := T{1, "one"}
// make struct copy
u := t // u has its field values equal to t
if u == t { // true
fmt.Println("u and t are equal") // Prints: "u and t are equal"
}
在上面的例子中,'t'
和’u’現在是單獨的物件(結構值)。
由於 T
不包含任何引用型別(切片,地圖,通道)作為其欄位,因此可以修改上面的 t
和 u
而不會相互影響。
fmt.Printf("t.I = %d, u.I = %d\n", t.I, u.I) // t.I = 100, u.I = 1
但是,如果 T
包含引用型別,例如:
type T struct {
I int
S string
xs []int // a slice is a reference type
}
然後,通過賦值的簡單副本將切片型別欄位的值也複製到新物件。這將導致兩個不同的物件引用相同的切片物件。
// initialize a struct
t := T{I: 1, S: "one", xs: []int{1, 2, 3}}
// make struct copy
u := t // u has its field values equal to t
由於 u 和 t 都通過其欄位 xs 引用相同的切片,因此更新一個物件的切片中的值將反映另一個物件的更改。
// update a slice field in u
u.xs[1] = 500
fmt.Printf("t.xs = %d, u.xs = %d\n", t.xs, u.xs)
// t.xs = [1 500 3], u.xs = [1 500 3]
因此,必須格外小心以確保此引用型別屬性不會產生意外行為。
例如,要複製上述物件,可以執行切片欄位的顯式副本:
// explicitly initialize u's slice field
u.xs = make([]int, len(t.xs))
// copy the slice values over from t
copy(u.xs, t.xs)
// updating slice value in u will not affect t
u.xs[1] = 500
fmt.Printf("t.xs = %d, u.xs = %d\n", t.xs, u.xs)
// t.xs = [1 2 3], u.xs = [1 500 3]