deepclone

package module
v0.2.15 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 18, 2026 License: MIT Imports: 3 Imported by: 3

README

DeepClone

A high-performance deep cloning library for Go that provides safe, efficient copying of any Go value.

Go Module License Go Report Card

Features

  • High Performance: Zero-allocation fast paths for primitive types
  • Circular Reference Safe: Automatic detection and handling of circular references
  • Thread Safe: Concurrent operations with safe caching mechanisms
  • Universal Support: Works with all Go types including channels, functions, and interfaces
  • Extensible: Custom cloning behavior via Cloneable interface
  • Zero Dependencies: Uses only Go standard library

Installation

go get github.com/kaptinlin/deepclone

Quick Start

package main

import (
    "fmt"
    "github.com/kaptinlin/deepclone"
)

func main() {
    // Deep clone any value
    original := map[string][]int{
        "numbers": {1, 2, 3},
        "scores":  {85, 90, 95},
    }

    cloned := deepclone.Clone(original)

    // Modify original - cloned remains independent
    original["numbers"][0] = 999

    fmt.Println("Original:", original["numbers"]) // [999, 2, 3]
    fmt.Println("Cloned:", cloned["numbers"])     // [1, 2, 3]
}

Core Concept

All operations perform deep copies by default:

  • Primitives: int, string, bool -- Copied by value (zero allocations)
  • Collections: slice, map, array -- New containers with cloned elements
  • Structs: New instances with all fields deeply cloned
  • Pointers: New pointers pointing to cloned values
  • Custom Types: Support via Cloneable interface

Examples

Basic Usage
// Primitives (zero allocation)
number := deepclone.Clone(42)
text := deepclone.Clone("hello")

// Collections (deep cloned)
slice := deepclone.Clone([]string{"a", "b", "c"})
data := deepclone.Clone(map[string]int{"key": 42})

// Complex structures
type User struct {
    Name    string
    Friends []string
    Config  map[string]interface{}
}

user := User{
    Name:    "Alice",
    Friends: []string{"Bob", "Charlie"},
    Config:  map[string]interface{}{"theme": "dark"},
}

cloned := deepclone.Clone(user) // Complete deep copy
Custom Cloning Behavior
type Document struct {
    Title   string
    Content []byte
    Version int
}

// Implement custom cloning logic
func (d Document) Clone() any {
    return Document{
        Title:   d.Title,
        Content: deepclone.Clone(d.Content).([]byte),
        Version: d.Version + 1, // Increment version on clone
    }
}

doc := Document{Title: "My Doc", Version: 1}
cloned := deepclone.Clone(doc) // Version becomes 2

For more examples, see examples/ directory.

Performance

DeepClone is optimized for performance with:

  • Zero allocations for primitive types
  • Fast paths for common slice/map types
  • Reflection caching for struct types
  • Minimal overhead for complex operations
Benchmark Results

Tested on Apple M3, macOS (darwin/arm64):

Operation Performance Memory Allocations
Primitives (int/string/bool) 2.7-3.6 ns/op 0 B/op 0 allocs/op
Slice (100 ints) 200.6 ns/op 896 B/op 1 allocs/op
Map (100 entries) 4,299 ns/op 3,544 B/op 4 allocs/op
Simple Struct 248.6 ns/op 128 B/op 4 allocs/op
Nested Struct 1,386 ns/op 952 B/op 19 allocs/op
Large Slice (10K ints) 6,709 ns/op 81,920 B/op 1 allocs/op

For detailed benchmarks and comparisons with other libraries, see benchmarks/.

# Run benchmarks
cd benchmarks && go test -bench=. -benchmem

API Reference

Core Function
func Clone[T any](src T) T

Creates a deep copy of any value. The returned value is completely independent of the original.

Custom Cloning Interface
type Cloneable interface {
    Clone() any
}

Implement this interface to provide custom cloning behavior for your types.

Advanced Features

  • Circular Reference Detection: Prevents infinite loops in self-referencing structures
  • Interface Preservation: Maintains original interface types while cloning concrete values
  • Thread Safety: All operations are safe for concurrent use
  • Type Caching: Struct metadata is cached for improved performance on repeated operations

Contributing

We welcome contributions! Please feel free to:

  • Report bugs
  • Suggest new features
  • Submit pull requests
  • Improve documentation

Requirements

  • Go 1.26 or later
  • No external dependencies

License

This project is licensed under the MIT License - see the LICENSE file for details.

Documentation

Overview

Package deepclone provides deep cloning with fast paths for common value, slice, and map types and reflection-based cloning for the rest.

Clone preserves object graphs, including circular references, when it falls back to reflection. Types that implement Cloneable provide their own cloning behavior and are responsible for handling cycles inside that method.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func CacheStats added in v0.2.4

func CacheStats() (entries, fields int)

CacheStats returns the number of cached struct types and fields.

Example
package main

import (
	"fmt"

	"github.com/kaptinlin/deepclone"
)

func main() {
	deepclone.ResetCache()

	type Point struct{ X, Y int }
	_ = deepclone.Clone(Point{1, 2})

	entries, fields := deepclone.CacheStats()
	fmt.Println("entries:", entries)
	fmt.Println("fields:", fields)
}
Output:
entries: 1
fields: 2

func Clone

func Clone[T any](src T) T

Clone returns a deep copy of src.

Clone preserves circular references when it uses reflection. Types that implement Cloneable control their own cloning behavior.

Example
package main

import (
	"fmt"

	"github.com/kaptinlin/deepclone"
)

func main() {
	original := map[string][]int{
		"scores": {90, 85, 77},
	}
	cloned := deepclone.Clone(original)

	// Modify the clone — original is unaffected
	cloned["scores"][0] = 100

	fmt.Println("original:", original["scores"])
	fmt.Println("cloned:  ", cloned["scores"])
}
Output:
original: [90 85 77]
cloned:   [100 85 77]
Example (Nil)
package main

import (
	"fmt"

	"github.com/kaptinlin/deepclone"
)

func main() {
	var original []int
	cloned := deepclone.Clone(original)

	fmt.Println("nil preserved:", cloned == nil)
}
Output:
nil preserved: true
Example (Slice)
package main

import (
	"fmt"

	"github.com/kaptinlin/deepclone"
)

func main() {
	original := []string{"a", "b", "c"}
	cloned := deepclone.Clone(original)

	cloned[0] = "z"

	fmt.Println("original:", original)
	fmt.Println("cloned:  ", cloned)
}
Output:
original: [a b c]
cloned:   [z b c]
Example (Struct)
package main

import (
	"fmt"

	"github.com/kaptinlin/deepclone"
)

func main() {
	type Address struct {
		City  string
		State string
	}
	type Person struct {
		Name    string
		Age     int
		Address *Address
	}

	original := Person{
		Name: "Alice",
		Age:  30,
		Address: &Address{
			City:  "Portland",
			State: "OR",
		},
	}
	cloned := deepclone.Clone(original)

	// Modify the clone's nested pointer — original is unaffected
	cloned.Address.City = "Seattle"
	cloned.Address.State = "WA"

	fmt.Println("original:", original.Address.City, original.Address.State)
	fmt.Println("cloned:  ", cloned.Address.City, cloned.Address.State)
}
Output:
original: Portland OR
cloned:   Seattle WA

func ResetCache added in v0.2.4

func ResetCache()

ResetCache clears the cached struct metadata.

Example
package main

import (
	"fmt"

	"github.com/kaptinlin/deepclone"
)

func main() {
	type Coord struct{ X, Y int }
	_ = deepclone.Clone(Coord{1, 2})

	deepclone.ResetCache()

	entries, _ := deepclone.CacheStats()
	fmt.Println("entries after reset:", entries)
}
Output:
entries after reset: 0

Types

type Cloneable

type Cloneable interface {
	// Clone returns a copy that can be used independently of the original.
	Clone() any
}

Cloneable lets a type define its own deep-cloning behavior.

Clone must return a copy that can be used independently of the original. Circular reference detection does not apply inside custom Clone methods.

Example
package main

import (
	"fmt"

	"github.com/kaptinlin/deepclone"
)

// Document is a type that implements the Cloneable interface
// to provide custom deep cloning behavior.
type Document struct {
	Title string
	Tags  []string
}

func (d Document) Clone() any {
	return Document{
		Title: d.Title,
		Tags:  deepclone.Clone(d.Tags),
	}
}

func main() {
	original := Document{
		Title: "Guide",
		Tags:  []string{"go", "clone"},
	}
	cloned := deepclone.Clone(original)

	cloned.Tags[0] = "rust"

	fmt.Println("original:", original.Tags)
	fmt.Println("cloned:  ", cloned.Tags)
}
Output:
original: [go clone]
cloned:   [rust clone]

Directories

Path Synopsis
examples
basic command
Package main demonstrates basic usage of the deepclone library.
Package main demonstrates basic usage of the deepclone library.
circular command
Package main demonstrates handling circular references with the deepclone library.
Package main demonstrates handling circular references with the deepclone library.
custom command
Package main demonstrates custom cloning behavior with the deepclone library.
Package main demonstrates custom cloning behavior with the deepclone library.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL