Documentation
¶
Overview ¶
Package deepclone copies Go state that can be observed and rebuilt through safe reflection. Types own inaccessible private state through Cloner[T].
Clone returns a deep copy or an error when a value cannot be honestly cloned. MustClone is the convenience form for values that are known to be supported.
Reflection cloning preserves supported object graphs, including circular references. Nil pointers, slices, maps, interfaces, channels, functions, and unsafe pointers keep their nil meaning. Non-nil channels, functions, and unsafe pointers are rejected because they represent runtime identity or execution capability rather than cloneable structural data. Slice capacity is an allocation detail, not a public cloning guarantee. Pointer-to-field and pointer-to-array-element relationships are preserved only when the addressable owner is cloned in the same graph.
The package does not use unsafe to read or write unexported fields. Reflection cloning preserves value-like unexported fields by shallow-copying the struct first, but rejects unexported reference-like state that it cannot safely deep-clone. Named external types report that failure at their public type boundary instead of exposing private layout. Types with private invariants or resource ownership should implement Cloner[T] and define an equivalent copy.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Clone ¶
Clone returns a deep copy of src.
Clone preserves circular references when it uses reflection. Types that implement Cloner[T] 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, err := deepclone.Clone(original)
if err != nil {
panic(err)
}
// 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.MustClone(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.MustClone(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.MustClone(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
Types ¶
type Cloner ¶ added in v0.2.17
type Cloner[T any] interface { // Clone returns a logically equivalent, independent copy. Clone() (T, error) }
Cloner lets a type define its own deep-cloning behavior.
Clone must preserve the value's logical meaning and return a copy whose mutable state 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 Cloner interface
// to provide custom deep cloning behavior.
type Document struct {
Title string
Tags []string
}
func (d Document) Clone() (Document, error) {
tags, err := deepclone.Clone(d.Tags)
if err != nil {
return Document{}, err
}
return Document{
Title: d.Title,
Tags: tags,
}, nil
}
func main() {
original := Document{
Title: "Guide",
Tags: []string{"go", "clone"},
}
cloned := deepclone.MustClone(original)
cloned.Tags[0] = "rust"
fmt.Println("original:", original.Tags)
fmt.Println("cloned: ", cloned.Tags)
}
Output: original: [go clone] cloned: [rust clone]
type UnsupportedError ¶ added in v0.2.17
UnsupportedError reports a value that cannot be honestly deep-cloned.
func (*UnsupportedError) Error ¶ added in v0.2.17
func (e *UnsupportedError) Error() string
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. |