How do I copy a struct in Golang?
In go, primitive types, and structs containing only primitive types, are copied by value, so you can copy them by simply assigning to a new variable (or returning from a function). For example:
type Person struct{
Name string
Age int
}
alice1 := Person{"Alice", 30}
alice2 := alice1
fmt.Println(alice1 == alice2) // => true, they have the same field values
fmt.Println(&alice1 == &alice2) // => false, they have different addresses
alice2.Age += 10
fmt.Println(alice1 == alice2) // => false, now they have different field values
Note that, as mentioned by commenters, the confusion in your example is likely due to the semantics of the test library you are using.
If your struct happens to include arrays, slices, or pointers, then you'll need to perform a deep copy of the referenced objects unless you want to retain references between copies. Golang provides no builtin deep copy functionality so you'll have to implement your own or use one of the many freely available libraries that provide it.
Be careful, if your source struct
is actually a pointer, then a normal assign won't work:
package main
import "net/http"
func main() {
a, err := http.NewRequest("GET", "https://stackoverflow.com", nil)
if err != nil {
panic(err)
}
b := a.URL
b.Host = "superuser.com"
println(a.URL.Host == "superuser.com")
}
Instead, you need to dereference the pointer:
package main
import "net/http"
func main() {
a, err := http.NewRequest("GET", "https://stackoverflow.com", nil)
if err != nil {
panic(err)
}
b := *a.URL
b.Host = "superuser.com"
println(a.URL.Host == "stackoverflow.com")
}
You can use a function with pass by value and return the argument untouched or changed depending on your needs.
Using the structs from above:
func main() {
copyOf := func(y Person) Person {
y.name = "Polonius"
y.address = append(y.address, Address{
city: "other city",
state: "other state",
})
return y
}
p := Person{
age: 20,
name: "Jack",
address: []Address{
{
city: "city1",
state: "state1",
}, {
city: "city2",
state: "state2",
},
},
}
q := copyOf(p)
fmt.Printf("Orig %v, \naddrss: %p \n\n", p, &p)
fmt.Printf("Copy %v, \naddress: %p\n\n", q, &q)
}
DeepCopy is a very heavy operation and hence should be avoided if possible. For complex structures such as the following, we can optimise the code.
type Address struct {
city string
state string
}
type Person struct {
age int
name string
address []Address
}
p := Person{
age: 20,
name: "Jack",
address: []Address{
{
city: "city1",
state: "state1",
}, {
city: "city2",
state: "state2",
},
},
}
var q Person
q.age = p.age
q.name = p.name
q.address = append(q.address, p.address...)
q.address[0].city = "cityx"
Result:
p object:
{20 Jack [{city1 state1} {city2 state2}]}
q object:
{20 Jack [{cityx state1} {city2 state2}]}
Inference:
As can be seen from the above example, the p object did not change when q was changed. This approach can be used in nested array of structs.