Deepcopy
Create deep copies (clones) of your maps and slices without using reflection.
Install / Use
/learn @gohobby/DeepcopyREADME
DeepCopy
DeepCopy helps you create deep copies (clones) of your maps and slices.
The package is based on type assertions and does not use reflection.
Installation
Install DeepCopy with the go get
command:
go get -u github.com/gohobby/deepcopy
How it works
DeepCopy returns a new object with all recursively duplicated children. This means that changes made to the original object will not affect the copied object and vice versa.
To copy a card or a slice:
m := map[string]interface{}{"foo": []string{"bar", "baz"}}
cloneMap := deepcopy.Map(m).DeepCopy() // interface{}
s := []interface{}{1, 2, &m}
cloneSlice := deepcopy.Slice(s).DeepCopy() // interface{}
You can also use the Clone function to get the copy directly into the expected type, for example:
m := map[string]interface{}{"foo": []string{"bar", "baz"}}
cloneMap := deepcopy.Map(m).CLone() // map[string]interface{}
s := []interface{}{1, 2, &m}
cloneSlice := deepcopy.Slice(s).Clone() // []interface{}
To copy your custom types, implement the Copyable interface and define your own deep copy function:
type Map map[string]interface{}
func (n Map) DeepCopy() interface{} {
clone := make(Map, len(n))
for k, v := range n {
clone[k] = deepcopy.DeepCopy(v)
}
return clone
}
<details><summary>Example</summary>
<p>
package main
import (
"fmt"
"github.com/gohobby/deepcopy"
)
type Map map[string]interface{}
func (n Map) DeepCopy() interface{} {
clone := make(Map, len(n))
for k, v := range n {
clone[k] = deepcopy.DeepCopy(v)
}
return clone
}
var nestedMap = Map{
"flag": "🇫🇷",
"country": Map{
"city": "Paris",
},
}
func main() {
// Deep Copy
deepClone := nestedMap.DeepCopy().(Map)
// Change of the cloned object
deepClone["flag"] = "🇮🇹"
deepClone["country"].(Map)["city"] = "Roma"
fmt.Printf("%#v\n", deepClone)
// main.Map{"country":main.Map{"city":"Roma"}, "flag":"🇮🇹"} <-- ✅
fmt.Printf("%#v\n\n", nestedMap)
// main.Map{"country":main.Map{"city":"Paris"}, "flag":"🇫🇷"} <-- ✅
fmt.Printf("%p\n", deepClone["country"]) // 0xc000012240
fmt.Printf("%p\n", nestedMap["country"]) // 0xc0000121e0
}
</p>
</details>
Why?
Mutability
Map types are pointers which make them mutable objects.
When you write the statement
m := make(map[int]int)
The compiler replaces it with a call to runtime.makemap, which has the signature
// makemap implements Go map creation for make(map[k]v, hint).
// If the compiler has determined that the map or the first bucket
// can be created on the stack, h and/or bucket may be non-nil.
// If h != nil, the map can be created directly in h.
// If h.buckets != nil, bucket pointed to can be used as the first bucket.
func makemap(t *maptype, hint int, h *hmap) *hmap
As you can see, the type of the value returned by runtime.makemap is a pointer to
a runtime.hmap
structure.
See Dave Cheney's article for more details.
<details><summary>Example</summary> <p>package main
import "fmt"
func main() {
obj := map[string]int{"one": 1, "two": 2}
obj2 := obj
fmt.Printf("(obj) %v\n(obj2) %v\n\n",
obj, // map[one:1 two:2]
obj2, // map[one:1 two:2]
)
obj2["three"] = 3
fmt.Printf("(obj2) %v\n", obj2)
// map[one:1 three:3 two:2] <-- ✅
fmt.Printf("(obj) %v\n", obj)
// map[one:1 three:3 two:2] <-- ❌
}
</p>
</details>
How to create copies of your maps?
Shallow Copy
A shallow copy means that the first level is copied, deeper levels are referenced.
<img width="405" alt="shallowcopy" src="https://user-images.githubusercontent.com/27848278/143790856-38ba7f3c-0664-4d89-bf1f-62f8763df874.png"> <details><summary>Example</summary> <p>package main
import "fmt"
var nestedObject = map[string]interface{}{
"flag": "🇫🇷",
"country": map[string]interface{}{
"city": "Paris",
},
}
func main() {
// Shallow Copy
shallowClone := make(map[string]interface{}, len(nestedObject))
for k, v := range nestedObject {
shallowClone[k] = v
}
// Change of the cloned object
shallowClone["flag"] = "🇮🇹"
shallowClone["country"].(map[string]interface{})["city"] = "Roma"
fmt.Printf("%v\n", shallowClone)
// map[country:map[city:Roma] flag:🇮🇹] <-- ✅
fmt.Printf("%v\n\n", nestedObject)
// map[country:map[city:Roma] flag:🇫🇷] <-- ❌ was mutated
fmt.Printf("%p\n", shallowClone["country"]) // 0xc0000121e0
fmt.Printf("%p\n", nestedObject["country"]) // 0xc0000121e0
}
</p>
</details>
Deep Copy
A deep copy is a shallow copy applied recursively to all sub objects.
<img width="407" alt="deepcopy" src="https://user-images.githubusercontent.com/27848278/143790774-4529a437-5bd7-4df0-ad35-9ae675480852.png"> <details><summary>Example</summary> <p>package main
import (
"fmt"
"github.com/gohobby/deepcopy"
)
var nestedObject = map[string]interface{}{
"flag": "🇫🇷",
"country": map[string]interface{}{
"city": "Paris",
},
}
func main() {
// Deep Copy
deepClone := deepcopy.Map(nestedObject).Clone()
// Change of the cloned object
deepClone["flag"] = "🇮🇹"
deepClone["country"].(map[string]interface{})["city"] = "Roma"
fmt.Printf("%v\n", deepClone)
// map[country:map[city:Roma] flag:🇮🇹] <-- ✅
fmt.Printf("%v\n\n", nestedObject)
// map[country:map[city:Paris] flag:🇫🇷] <-- ✅
fmt.Printf("%p\n", deepClone["country"]) // 0xc000012240
fmt.Printf("%p\n", nestedObject["country"]) // 0xc0000121e0
}
</p>
</details>Related Skills
node-connect
346.8kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
xurl
346.8kA CLI tool for making authenticated requests to the X (Twitter) API. Use this skill when you need to post tweets, reply, quote, search, read posts, manage followers, send DMs, upload media, or interact with any X API v2 endpoint.
frontend-design
107.6kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
346.8kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
