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.
struct
struct2 := &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.struct
Deep 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-package
be used for doing this.
Free Resources