Create deep copies (clones) of your maps and slices without using reflection.

Overview

DeepCopy

Go Reference Go Report Card Go Cover Test

DeepCopy helps you create deep copies (clones) of your maps and slices. Create deep copies (clones) of your objects

The package is based on type assertions and does not use reflection.

Installation

Install DeepCopy with the go get command:

go get -u github.con/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{}

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.

Example:

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] <-- ❌

Run this code in GoPlayground

How to create copies of your maps?

Shallow Copy

A shallow copy means that the first level is copied, deeper levels are referenced.

Example:

type Map map[string]interface{}

var nestedMap = Map{
"flag": "🇫🇷",
"country": Map{
"city": "Paris",
},
}

// Shallow Copy
shallowClone := make(Map, len(nestedMap))

for k, v := range nestedMap {
shallowClone[k] = v
}

// Change of the cloned object
shallowClone["flag"] = "🇮🇹"
shallowClone["country"].(Map)["city"] = "Roma"

fmt.Printf("%v\n", shallowClone)
// map[country:map[city:Roma] flag:🇮🇹] <-- ✅

fmt.Printf("%v\n", nestedMap)
// map[country:map[city:Roma] flag:🇫🇷] <-- ❌

fmt.Printf("%p\n", nestedMap["country"]) // 0xc0000121e0
fmt.Printf("%p\n", shallowClone["country"]) // 0xc0000121e0

Run this code in GoPlayground

Deep Copy

A deep copy is a shallow copy applied recursively to all sub objects.

Example:

deepClone := deepcopy.Map(nestedMap).Clone()

fmt.Printf("%v\n", deepClone)
// map[country:map[city:Roma] flag:🇮🇹] <-- ✅

fmt.Printf("%v\n", nestedMap)
// map[country:map[city:Paris] flag:🇫🇷] <-- ✅
Releases(v1.0.0)
  • v1.0.0(Nov 29, 2021)

    What's Changed

    • chore: add test for copyable interface with nested map by @T-Hugo in https://github.com/gohobby/deepcopy/pull/4

    Full Changelog: https://github.com/gohobby/deepcopy/compare/v0.0.2...v1.0.0

    Source code(tar.gz)
    Source code(zip)
  • v0.0.2(Nov 29, 2021)

    What's Changed

    • docs: update README.md by @T-Hugo in https://github.com/gohobby/deepcopy/pull/3

    Full Changelog: https://github.com/gohobby/deepcopy/compare/v0.0.1...v0.0.2

    Source code(tar.gz)
    Source code(zip)
A Go package for checking conditions for slices and maps.

check Go package The check package of Go helps one to check various conditions for slices: []int []float64 []string []bool maps: map[string]int map[st

null 4 Feb 3, 2022
Optimal implementation of ordered maps for Golang - ie maps that remember the order in which keys were inserted.

Goland Ordered Maps Same as regular maps, but also remembers the order in which keys were inserted, akin to Python's collections.OrderedDicts. It offe

Jean Rougé 183 May 17, 2022
Bitwise AND on two byte-slices using SIMD instructions

This package provides a vectorised function which performs bitwise AND operation on all pairs of elements in two byte-slices. It detects CPU instruction set and chooses the available best one (AVX512, AVX2, SSE2).

Wei Shen 5 Dec 10, 2021
Access and modify property values in deeply nested maps, using dot-separated paths

Dig lets you access and modify property values in deeply nested, unstructured maps, using dot-separated paths: source := make(map[string]interface{})

Preslav Rachev 12 May 7, 2022
A program to create assembly 8086 strings to print without using any printing/strings related function but only mov-xchg-int and loops

Assembly String builder tool A program to create assembly 8086 strings to print without using any printing/strings related function but only mov-xchg-

Reg 2 Feb 1, 2022
Helpers for making the use of reflection easier

go-xray This is a Golang library with reflection related functions which I use in my different projects. KeyValue This type is used to construct a key

Pieter Claerhout 21 Mar 3, 2022
A Go preprocessor for package scoped reflection

pkgreflect - A Go preprocessor for package scoped reflection Problem: Go reflection does not support enumerating types, variables and functions of pac

Erik Unger 99 Sep 7, 2021
Faster golang reflection

In order to solve a problem that can work with any golang type, one has no choice but to use reflection. Native golang reflection comes with hefty performance price, on benchmarking simple getter/setter case to manipulate struct dynamically I've seen around 100 time worst performance comparing to statically typed code.

Viant, Inc 5 Apr 14, 2022
Di - A (very) WIP Go 1.18+ generic dependency injection package based on type reflection

di A (very) WIP Go 1.18+ generic dependency injection package based on type refl

Ringo Hoffmann 5 Apr 26, 2022
Extremely flexible golang deep comparison, extends the go testing package, tests HTTP APIs and provides tests suite

go-testdeep Extremely flexible golang deep comparison, extends the go testing package. Latest news Synopsis Description Installation Functions Availab

Maxime Soulé 281 May 16, 2022
A go1.18+ package to (maybe) simplify performing operations on slices in a fluent-like style.

sop ✨ W.I.P. ✨ sop (slices operation) is a go1.18+ package to (maybe) simplify performing operations on slices in a fluent-like style with common oper

Ringo Hoffmann 3 Mar 17, 2022
Automatically creates & tiles .tmx format maps from a world map interface

Autotile Create tiled maps for an arbitrarily large world space from a simple interface, then add larger objects randomly with simple rules (eg. place

null 0 Jan 9, 2022
Hotswap provides a solution for reloading your go code without restarting your server, interrupting or blocking any ongoing procedure.

Hotswap provides a solution for reloading your go code without restarting your server, interrupting or blocking any ongoing procedure. Hotswap is built upon the plugin mechanism.

Edwin 75 May 12, 2022
efaceconv - Code generation tool for high performance conversion from interface{} to immutable type without allocations.

efaceconv High performance conversion from interface{} to immutable types without additional allocations This is tool for go generate and common lib (

Ivan 50 May 14, 2022
reflect api without runtime reflect.Value cost

reflect2 reflect api that avoids runtime reflect.Value cost reflect get/set interface{}, with type checking reflect get/set unsafe.Pointer, without ty

Modern Go Programming 564 May 10, 2022
Execute a binary from memory, without touching the disk. Linux only.

Memit Execute a binary from memory, without touching the disk. Linux only. Available as both a Go module and a binary. Using the Go module The Command

Liam Galvin 221 May 9, 2022
Little helper to create tar balls of an executable together with its ELF shared library dependencies.

Little helper to create tar balls of an executable together with its ELF shared library dependencies. This is useful for prototyping with gokrazy: htt

null 1 Nov 4, 2021
The main goal of this code is to create a basic dnstap printing tool based on the golang-dnstap library.

dnstap-parse The main goal of this code is to create a basic dnstap printing tool based on the golang-dnstap library. The output is supposed to mimic

Patrik Lundin 1 Nov 14, 2021
A fully Go userland with Linux bootloaders! u-root can create a one-binary root file system (initramfs) containing a busybox-like set of tools written in Go.

u-root Description u-root embodies four different projects. Go versions of many standard Linux tools, such as ls, cp, or shutdown. See cmds/core for m

null 1.9k May 17, 2022