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

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:🇫🇷] <-- ✅
Comments
  • Panic for nested map with nil fields

    Panic for nested map with nil fields

    Hello! It throws a panic for nested map with with nil fields.

    package main
    
    import (
    	"encoding/json"
    
    	"github.com/gohobby/deepcopy"
    )
    
    var msg = `
    {
        "one": {
            "two": null
        }
    }
    `
    
    func main() {
    	var payload map[string]any
    	json.Unmarshal([]byte(msg), &payload)
    	deepcopy.Map(payload).Clone()
    }
    
    panic: interface conversion: interface is nil, not interface {}
    
    goroutine 1 [running]:
    github.com/gohobby/deepcopy.DeepCopy({0x4ba120?, 0xc000012270?})
    	/tmp/gopath900186122/pkg/mod/github.com/gohobby/[email protected]/deepcopy.go:277 +0x4bb7
    github.com/gohobby/deepcopy.Map.DeepCopy(0xc0000121b0)
    	/tmp/gopath900186122/pkg/mod/github.com/gohobby/[email protected]/deepcopy_map.go:13 +0xc7
    github.com/gohobby/deepcopy.Map.Clone(...)
    	/tmp/gopath900186122/pkg/mod/github.com/gohobby/[email protected]/deepcopy_map.go:22
    main.main()
    	/tmp/sandbox2139623867/prog.go:20 +0x5d
    
    Program exited.
    
  • chore(deps): bump github.com/dave/jennifer from 1.5.1 to 1.6.0

    chore(deps): bump github.com/dave/jennifer from 1.5.1 to 1.6.0

    Bumps github.com/dave/jennifer from 1.5.1 to 1.6.0.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
  • chore(deps): bump actions/checkout from 2 to 3

    chore(deps): bump actions/checkout from 2 to 3

    Bumps actions/checkout from 2 to 3.

    Release notes

    Sourced from actions/checkout's releases.

    v3.0.0

    • Updated to the node16 runtime by default
      • This requires a minimum Actions Runner version of v2.285.0 to run, which is by default available in GHES 3.4 or later.

    v2.4.2

    What's Changed

    Full Changelog: https://github.com/actions/checkout/compare/v2...v2.4.2

    v2.4.1

    • Fixed an issue where checkout failed to run in container jobs due to the new git setting safe.directory

    v2.4.0

    • Convert SSH URLs like org-<ORG_ID>@github.com: to https://github.com/ - pr

    v2.3.5

    Update dependencies

    v2.3.4

    v2.3.3

    v2.3.2

    Add Third Party License Information to Dist Files

    v2.3.1

    Fix default branch resolution for .wiki and when using SSH

    v2.3.0

    Fallback to the default branch

    v2.2.0

    Fetch all history for all tags and branches when fetch-depth=0

    v2.1.1

    Changes to support GHES (here and here)

    v2.1.0

    ... (truncated)

    Changelog

    Sourced from actions/checkout's changelog.

    Changelog

    v3.0.2

    v3.0.1

    v3.0.0

    v2.3.1

    v2.3.0

    v2.2.0

    v2.1.1

    • Changes to support GHES (here and here)

    v2.1.0

    v2.0.0

    v2 (beta)

    • Improved fetch performance

    ... (truncated)

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
  • chore(deps): bump actions/setup-go from 2 to 3

    chore(deps): bump actions/setup-go from 2 to 3

    Bumps actions/setup-go from 2 to 3.

    Release notes

    Sourced from actions/setup-go's releases.

    Update actions/cache version to 3.0.0

    In scope of this release we updated actions/cache package as the new version contains fixes for caching error handling

    v3.0.0

    What's Changed

    Breaking Changes

    With the update to Node 16, all scripts will now be run with Node 16 rather than Node 12.

    This new major release removes the stable input, so there is no need to specify additional input to use pre-release versions. This release also corrects the pre-release versions syntax to satisfy the SemVer notation (1.18.0-beta1 -> 1.18.0-beta.1, 1.18.0-rc1 -> 1.18.0-rc.1).

    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-go@v3
        with:
          go-version: '1.18.0-rc.1' 
      - run: go version
    

    Add check-latest input

    In scope of this release we add the check-latest input. If check-latest is set to true, the action first checks if the cached version is the latest one. If the locally cached version is not the most up-to-date, a Go version will then be downloaded from go-versions repository. By default check-latest is set to false. Example of usage:

    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-go@v2
        with:
          go-version: '1.16'
          check-latest: true
      - run: go version
    

    Moreover, we updated @actions/core from 1.2.6 to 1.6.0

    v2.1.5

    In scope of this release we updated matchers.json to improve the problem matcher pattern. For more information please refer to this pull request

    v2.1.4

    What's Changed

    New Contributors

    Full Changelog: https://github.com/actions/setup-go/compare/v2.1.3...v2.1.4

    v2.1.3

    • Updated communication with runner to use environment files rather then workflow commands

    ... (truncated)

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
  • chore(deps): bump github.com/dave/jennifer from 1.4.1 to 1.5.1

    chore(deps): bump github.com/dave/jennifer from 1.4.1 to 1.5.1

    Bumps github.com/dave/jennifer from 1.4.1 to 1.5.1.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
  • chore(deps): bump golangci/golangci-lint-action from 2 to 3

    chore(deps): bump golangci/golangci-lint-action from 2 to 3

    Bumps golangci/golangci-lint-action from 2 to 3.

    Release notes

    Sourced from golangci/golangci-lint-action's releases.

    v3.0.0

    What's Changed

    New Contributors

    Full Changelog: https://github.com/golangci/golangci-lint-action/compare/v2...v3.0.0

    Bump version v2.5.2

    Bug fixes

    • 5c56cd6 Extract and don't mangle User Args. (#200)

    Dependencies

    • e3c53fe bump @​typescript-eslint/eslint-plugin (#194)
    • 3b9f80e bump @​typescript-eslint/parser from 4.18.0 to 4.19.0 (#195)
    • 9845713 bump @​types/node from 14.14.35 to 14.14.37 (#197)
    • e789ee1 bump eslint from 7.22.0 to 7.23.0 (#196)
    • f2e9a96 bump @​typescript-eslint/eslint-plugin (#188)
    • 818081a bump @​types/node from 14.14.34 to 14.14.35 (#189)
    • 6671836 bump @​typescript-eslint/parser from 4.17.0 to 4.18.0 (#190)
    • 526907e bump @​typescript-eslint/parser from 4.16.1 to 4.17.0 (#185)
    • 6b6ba16 bump @​typescript-eslint/eslint-plugin (#186)
    • 9cab4ef bump eslint from 7.21.0 to 7.22.0 (#187)
    • 0c76572 bump @​types/node from 14.14.32 to 14.14.34 (#184)
    • 0dfde21 bump @​typescript-eslint/parser from 4.15.2 to 4.16.1 (#182)
    • 9dcf389 bump typescript from 4.2.2 to 4.2.3 (#181)
    • 34d3904 bump @​types/node from 14.14.31 to 14.14.32 (#180)
    • e30b22f bump @​typescript-eslint/eslint-plugin (#179)
    • 8f30d25 bump eslint from 7.20.0 to 7.21.0 (#177)
    • 0b64a40 bump @​typescript-eslint/parser from 4.15.1 to 4.15.2 (#176)
    • 973b3a3 bump eslint-config-prettier from 8.0.0 to 8.1.0 (#178)
    • 6ea3de1 bump @​typescript-eslint/eslint-plugin (#175)
    • 6eec6af bump typescript from 4.1.5 to 4.2.2 (#174)

    v2.5.1

    Bug fixes:

    • d9f0e73 Check that go.mod exists in reading the version (#173)

    v2.5.0

    New Features:

    • 51485a4 Try to get version from go.mod file (#118)

    ... (truncated)

    Commits
    • 537aa19 Expire cache periodically to avoid unbounded size (#466)
    • f70e52d build(deps): bump @​actions/core from 1.6.0 to 1.8.0 (#468)
    • a304692 build(deps-dev): bump @​typescript-eslint/eslint-plugin (#469)
    • eeca7c5 build(deps-dev): bump eslint from 8.14.0 to 8.15.0 (#467)
    • dfbcd2a build(deps): bump github/codeql-action from 1 to 2 (#459)
    • 4421331 build(deps-dev): bump @​typescript-eslint/parser from 5.20.0 to 5.22.0 (#464)
    • 5e6c1bb build(deps-dev): bump typescript from 4.6.3 to 4.6.4 (#461)
    • 44eba43 build(deps-dev): bump @​typescript-eslint/eslint-plugin (#460)
    • 358a5e3 build(deps-dev): bump @​typescript-eslint/eslint-plugin (#457)
    • b9c65a5 build(deps-dev): bump @​typescript-eslint/parser from 5.19.0 to 5.20.0 (#455)
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
🍕 Enjoy a slice! A utility library for dealing with slices and maps that focuses on type safety and performance.

?? github.com/elliotchance/pie Enjoy a slice! pie is a library of utility functions for common operations on slices and maps. Quick Start FAQ What are

Dec 30, 2022
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

Aug 26, 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

Jan 3, 2023
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-

Feb 1, 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).

Oct 17, 2022
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{})

May 7, 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

Oct 24, 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

Dec 13, 2022
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.

Dec 21, 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

Apr 26, 2022
Extremely flexible golang deep comparison, extends the go testing package, tests HTTP APIs and provides tests suite
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

Jan 5, 2023
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 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.

Jan 5, 2023
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

Oct 1, 2022
Automatically creates & tiles .tmx format maps from a world map interface
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

Aug 19, 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 (

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

Jan 4, 2023
Execute a binary from memory, without touching the disk. Linux only.
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

Jan 5, 2023
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

Sep 7, 2022
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

Nov 14, 2021