Documentation
¶
Overview ¶
Package clone provides functions to deep clone any Go data. It also provides a wrapper to protect a pointer from any unexpected mutation.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Clone ¶
func Clone(v interface{}) interface{}
Clone recursively deep clone v to a new value. It assumes that there is no pointer cycle in v, e.g. v has a pointer points to v itself. If there is a pointer cycle, use Slowly instead.
In the most cases, Clone allocates new memory space for deep clone, instead of all scalar types and following special values.
- scalar types: all number-like types are copied by value.
- func: Copied by value as func is immutable at runtime.
- string: Copied by value as string is immutable by design.
- unsafe.Pointer: Copied by value as we don't know what's in it.
- chan: A new empty chan is cloned without any data inside.
Unlike many similar packages, Clone is able to clone unexported fields of any struct. Use this feature wisely.
func MarkAsScalar ¶ added in v1.1.2
MarkAsScalar marks t as a scalar type so that all clone methods will copy t by value. If t is not struct or pointer to struct, MarkAsScalar ignores t.
In the most cases, it's not necessary to call it explicitly. If a struct type contains scalar type fields only, the struct will be marked as scalar automatically.
Here is a list of types marked as scalar by default:
- time.Time
- reflect.Value
Example ¶
package main
import (
"fmt"
"os"
"reflect"
)
type ScalarType struct {
stderr *os.File
}
func main() {
MarkAsScalar(reflect.TypeOf(new(ScalarType)))
scalar := &ScalarType{
stderr: os.Stderr,
}
cloned := Clone(scalar).(*ScalarType)
// cloned is a shadow copy of scalar
// so that the pointer value should be the same.
fmt.Println(scalar.stderr == cloned.stderr)
}
Output: true
func Slowly ¶
func Slowly(v interface{}) interface{}
Slowly recursively deep clone v to a new value. It marks all cloned values internally, thus it can clone v with cycle pointer.
Slowly works exactly the same as Clone. See Clone doc for more details.
Example ¶
type ListNode struct {
Data int
Next *ListNode
}
node1 := &ListNode{
Data: 1,
}
node2 := &ListNode{
Data: 2,
}
node3 := &ListNode{
Data: 3,
}
node1.Next = node2
node2.Next = node3
node3.Next = node1
// We must use `Slowly` to clone a circular linked list.
node := Slowly(node1).(*ListNode)
for i := 0; i < 10; i++ {
fmt.Println(node.Data)
node = node.Next
}
Output: 1 2 3 1 2 3 1 2 3 1
func Undo ¶
func Undo(v interface{})
Undo discards any change made in wrapped value. If v is not a wrapped value, nothing happens.
func Unwrap ¶
func Unwrap(v interface{}) interface{}
Unwrap returns v's original value if v is a wrapped value. Otherwise, simply returns v itself.
func Wrap ¶
func Wrap(v interface{}) interface{}
Wrap creates a wrapper of v, which must be a pointer. If v is not a pointer, Wrap simply returns v and do nothing.
The wrapper is a deep clone of v's value. It holds a shadow copy to v internally.
t := &T{Foo: 123}
v := Wrap(t).(*T) // v is a clone of t.
reflect.DeepEqual(t, v) == true // v equals t.
v.Foo = 456 // v.Foo is changed, but t.Foo doesn't change.
orig := Unwrap(v) // Use `Unwrap` to discard wrapper and return original value, which is t.
orig.(*T) == t // orig and t is exactly the same.
Undo(v) // Use `Undo` to discard any change on v.
v.Foo == t.Foo // Now, the value of v and t are the same again.
Example ¶
// Suppose we have a type T defined as following.
// type T struct {
// Foo int
// }
v := &T{
Foo: 123,
}
w := Wrap(v).(*T) // Wrap value to protect it.
// Use w freely. The type of w is the same as that of v.
// It's OK to modify w. The change will not affect v.
w.Foo = 456
fmt.Println(w.Foo) // 456
fmt.Println(v.Foo) // 123
// Once we need the original value stored in w, call `Unwrap`.
orig := Unwrap(w).(*T)
fmt.Println(orig == v) // true
fmt.Println(orig.Foo) // 123
// Or, we can simply undo any change made in w.
// Note that `Undo` is significantly slower than `Unwrap`, thus
// the latter is always preferred.
Undo(w)
fmt.Println(w.Foo) // 123
Output: 456 123 true 123 123
Types ¶
This section is empty.