The Go language creates a deep copy of structs with primitive type fields by default. However, there is no built-in function to deep copy a struct that includes references. We can use a third-party provider to do this, or in the case that there is no third-party package or we simply don’t want to use it, we can build one ourselves.
To read more on the differences between deep copying and shallow copying, check this Answer.
Before seeing how to deep copy a struct, let’s look at how we can perform a shallow copy first.
structstruct2 := &struct1
For a pointer referencing a struct, we simply use an assignment operator to create a shallow copy.
struct2 := struct1
package mainimport "fmt"type DemoStruct struct{name string; value int}func main(){struct1 := DemoStruct{name: "int", value: 30}fmt.Println(struct1.name)struct2 := &struct1struct2.name = "string"fmt.Printf("Struct1 : %s\nStruct2 : %s\n",struct1.name, struct2.name)fmt.Println(&struct1 == struct2)}
struct1 to a new variable struct2.name to string in struct2.struct1 also reflects the change.structDeep copying a struct depends on one’s code implementation. The core concept is the same as that of shallow copying, namely we remove the reference and manually copy the content. However, the functions and the strategy may vary depending on the given scenario.
struct2 := struct1
This will only work for a struct with primitive fields.
For a pointer referencing a struct, we use * to dereference it before creating its copy.
struct with an array fieldHere we use the append function, but we can also use the map function to achieve the same functionality.
package mainimport "fmt"type DemoStruct struct{name stringvalue intarr []string}func main() {p := DemoStruct{value: 20,name: "Struct1",arr: []string{"city1"},}q:=pq.arr = nilq.arr = append(q.arr,p.arr...)q.arr[0]= "Altered"fmt.Println(p)fmt.Println(q)fmt.Println(&p == &q)}
nil to arr and remove the reference of the original array.q. Notice that this change is not reflected in the arr field of struct p.struct with a pointer fieldpackage mainimport "fmt"type DemoStruct struct{name stringvalue ints_pointer *string}func main() {x:= "Original"p := DemoStruct{ value: 20, name: "Struct1", s_pointer: &x }q:=pq.s_pointer = nily:= *p.s_pointerq.s_pointer = &y*q.s_pointer = "Altered"fmt.Println(*p.s_pointer)fmt.Println(*q.s_pointer)fmt.Println(&p.s_pointer == &q.s_pointer)}
struct.nil to s_pointer of q.p.s_pointer by using *. We then copy its content to variable y.y to q.s_pointer.We do not recommend that the
unsafe-packagebe used for doing this.
Free Resources