製作結構副本

可以使用賦值簡單地複製結構。

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 不包含任何引用型別(切片,地圖,通道)作為其欄位,因此可以修改上面的 tu 而不會相互影響。

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]