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.