Copy Structs in Go: Value Assignment, Pointers, Shallow vs Deep

Copy structs in Go: assignment copies the struct value; fields that are slices, maps, or pointers still alias shared backing data unless you duplicate them; primitives and arrays inside the struct copy by value.

Published

Updated

Read time 3 min read

Reviewed byDeepak Prasad

Copy Structs in Go: Value Assignment, Pointers, Shallow vs Deep

Struct assignment in Go copies the entire struct value in one assignment. That is a full copy of the struct’s own storage, but any field that contains a slice, map, or pointer still refers to the same underlying object as the source—what people often call a shallow copy of the aggregate. To test equality after copying, see compare structs, slices, and maps in Go. Primitives and fixed-size arrays inside the struct are independent after assignment. For pointers to structs, a new pointer can still refer to the same struct value, so mutations through the pointer affect every alias.

Animation: shallow struct copy in Go—slice fields still share the same backing array

Animation: deep struct copy in Go—duplicate slice fields so copies do not alias

Tested with Go 1.24 on Linux.


Primitives and strings

go
package main

import "fmt"

func main() {
	a := 64
	b := 12.5
	s := "Test string"
	a2, b2, s2 := a, b, s
	a2, b2, s2 = 105, 63, "Copy string"
	fmt.Println(a, b, s)
	fmt.Println(a2, b2, s2)
}
Output

You should see the originals unchanged on the first line and the updated copies on the second.


Slices and maps (shared backing)

go
package main

import "fmt"

func main() {
	testSlice := []int{1, 3, 4, 5, 6, 7, 1}
	testMap := map[string]int{"Red": 102, "Black": 253}
	copySlice := testSlice
	copyMap := testMap
	copySlice[0] = 10000000
	copyMap["Green"] = 1588963
	fmt.Println(testSlice[0], copySlice[0])
	fmt.Println(testMap["Green"], copyMap["Green"])
}
Output

You should see matching slice heads and the new map key visible on both variables.


Structs with only primitive fields

go
package main

import "fmt"

type Person struct {
	Name string
	Age  int
}

func main() {
	p1 := Person{"Anna", 23}
	p2 := p1
	p2.Name = "Bob"
	fmt.Println(p1.Name, p2.Name)
}
Output

You should see Anna and Bob.


Struct with a slice field (shared unless you copy)

go
package main

import "fmt"

type Person struct {
	Name    string
	Age     int
	Friends []string
}

func main() {
	p1 := Person{"Anna", 23, []string{"Bob", "Teddy", "Wilson"}}
	p2 := p1
	p2.Friends = append(p2.Friends, "Kelly")
	fmt.Println(len(p1.Friends), p1.Friends[len(p1.Friends)-1])
}
Output

You should see 4 and Kelly on the last element because p1 and p2 share the same backing array until you replace the slice field with an independent copy.

Taking the address with p3 := &p1 does not duplicate the struct; writes through p3 still hit the same value (including the same slice header) as p1.


Summary

Golang copy struct behavior is “copy the whole value once.” That duplicates primitive fields and array storage inside the struct, but slice, map, and pointer fields still alias unless you assign freshly allocated values (for example Friends: append([]string(nil), p1.Friends...)). Choose explicit duplication or serialization when you need full isolation.


References


Frequently Asked Questions

1. Does person2 := person1 deep copy a struct in Go?

It copies the struct value in one step. If a field holds a slice, map, or pointer, both variables see the same underlying data unless you rebuild those fields.

2. How is copying a struct different from copying a map or slice variable?

Assigning a map or slice variable copies the header that points to shared storage; struct assignment copies the whole struct bit pattern in one go, which still embeds those headers for reference-type fields.

3. How do I deep copy a struct with a slice field?

Copy the struct, then replace the slice field with a new slice and use copy() from the original, or use encoding/json, gob, or a small hand-written Clone method.

4. What does person2 := &person1 do?

person2 points at person1; changes through the pointer modify the same struct value including shared slice backing arrays.

5. Where can I read about pointers in Go?

See the pointers tutorial for addresses, dereferencing, and when to pass pointers to functions.
Tuan Nguyen

Data Scientist

Proficient in Golang, Python, Java, MongoDB, Selenium, Spring Boot, Kubernetes, Scrapy, API development, Docker, Data Scraping, PrimeFaces, Linux, Data Structures, and Data Mining. With expertise …