github.com/wfusion/gofusion@v1.1.14/common/utils/clone/api.go (about) 1 //go:build !go1.18 2 // +build !go1.18 3 4 package clone 5 6 // Clone recursively deep clone v to a new value in heap. 7 // It assumes that there is no pointer cycle in v, 8 // e.g. v has a pointer points to v itself. 9 // If there is a pointer cycle, use Slowly instead. 10 // 11 // Clone allocates memory and deeply copies values inside v in depth-first sequence. 12 // There are a few special rules for following types. 13 // 14 // - Scalar types: all number-like types are copied by value. 15 // - func: Copied by value as func is an opaque pointer at runtime. 16 // - string: Copied by value as string is immutable by design. 17 // - unsafe.Pointer: Copied by value as we don't know what's in it. 18 // - chan: A new empty chan is created as we cannot read data inside the old chan. 19 // 20 // Unlike many other packages, Clone is able to clone unexported fields of any struct. 21 // Use this feature wisely. 22 func Clone(v interface{}) interface{} { 23 return cloner.Clone(v) 24 } 25 26 // Slowly recursively deep clone v to a new value in heap. 27 // It marks all cloned values internally, thus it can clone v with cycle pointer. 28 // 29 // Slowly works exactly the same as Clone. See Clone doc for more details. 30 func Slowly(v interface{}) interface{} { 31 return cloner.CloneSlowly(v) 32 } 33 34 // Wrap creates a wrapper of v, which must be a pointer. 35 // If v is not a pointer, Wrap simply returns v and do nothing. 36 // 37 // The wrapper is a deep clone of v's value. It holds a shadow copy to v internally. 38 // 39 // t := &T{Foo: 123} 40 // v := Wrap(t).(*T) // v is a clone of t. 41 // reflect.DeepEqual(t, v) == true // v equals t. 42 // v.Foo = 456 // v.Foo is changed, but t.Foo doesn't change. 43 // orig := Unwrap(v) // Use `Unwrap` to discard wrapper and return original value, which is t. 44 // orig.(*T) == t // orig and t is exactly the same. 45 // Undo(v) // Use `Undo` to discard any change on v. 46 // v.Foo == t.Foo // Now, the value of v and t are the same again. 47 func Wrap(v interface{}) interface{} { 48 return wrap(t) 49 } 50 51 // Unwrap returns v's original value if v is a wrapped value. 52 // Otherwise, simply returns v itself. 53 func Unwrap(v interface{}) interface{} { 54 return unwrap(v) 55 } 56 57 // Undo discards any change made in wrapped value. 58 // If v is not a wrapped value, nothing happens. 59 func Undo(v interface{}) { 60 undo(v) 61 } 62 63 // MarkAsOpaquePointer marks t as an opaque pointer in heap allocator, 64 // so that all clone methods will copy t by value. 65 // If t is not a pointer, MarkAsOpaquePointer ignores t. 66 // 67 // Here is a list of types marked as opaque pointers by default: 68 // - `elliptic.Curve`, which is `*elliptic.CurveParam` or `elliptic.p256Curve`; 69 // - `reflect.Type`, which is `*reflect.rtype` defined in `runtime`. 70 func MarkAsOpaquePointer(t reflect.Type) { 71 markAsOpaquePointer(t) 72 } 73 74 // MarkAsScalar marks t as a scalar type in heap allocator, 75 // so that all clone methods will copy t by value. 76 // If t is not struct or pointer to struct, MarkAsScalar ignores t. 77 // 78 // In the most cases, it's not necessary to call it explicitly. 79 // If a struct type contains scalar type fields only, the struct will be marked as scalar automatically. 80 // 81 // Here is a list of types marked as scalar by default: 82 // - time.Time 83 // - reflect.Value 84 func MarkAsScalar(t reflect.Type) { 85 markAsScalar(t) 86 } 87 88 // SetCustomFunc sets a custom clone function for type t in heap allocator. 89 // If t is not struct or pointer to struct, SetCustomFunc ignores t. 90 // 91 // If fn is nil, remove the custom clone function for type t. 92 func SetCustomFunc(t reflect.Type, fn Func) { 93 setCustomFunc(t, fn) 94 } 95 96 // FromHeap creates an allocator which allocate memory from heap. 97 func FromHeap() *Allocator { 98 return fromHeap() 99 } 100 101 // NewAllocator creates an allocator which allocate memory from the pool. 102 // Both pool and methods are optional. 103 // 104 // If methods.New is not nil, the allocator itself is created by calling methods.New. 105 // 106 // The pool is a pointer to the memory pool which is opaque to the allocator. 107 // It's methods' responsibility to allocate memory from the pool properly. 108 func NewAllocator(pool unsafe.Pointer, methods *AllocatorMethods) (allocator *Allocator) { 109 return newAllocator(pool, methods) 110 }