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 recursive pointers in v, e.g. v has a pointer points to v itself.
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 recursive pointers in v.
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.