diff --git a/helpers/pointers.go b/helpers/pointers.go new file mode 100644 index 00000000..c38479af --- /dev/null +++ b/helpers/pointers.go @@ -0,0 +1,20 @@ +package helpers + +import "reflect" + +// ToPointer takes an interface{} object and will return a pointer to this object +// if the object is not already a pointer. Otherwise, it will return the original value. +// It is safe to typecast the return-value of GetPointer into a pointer of the right type, +// except in very special cases (such as passing in nil without an explicit type) +func ToPointer(v interface{}) interface{} { + val := reflect.ValueOf(v) + if val.Kind() == reflect.Ptr { + return v + } + if !val.IsValid() { + return v + } + p := reflect.New(val.Type()) + p.Elem().Set(val) + return p.Interface() +} diff --git a/helpers/pointers_test.go b/helpers/pointers_test.go new file mode 100644 index 00000000..2ae81ed7 --- /dev/null +++ b/helpers/pointers_test.go @@ -0,0 +1,50 @@ +package helpers + +import ( + "testing" +) + +type testStruct struct { + test string +} + +func TestToPointer(t *testing.T) { + // passing string should return pointer to string + give := "test" + got := ToPointer(give) + if _, ok := got.(*string); !ok { + t.Errorf("ToPointer(%q) returned %q, expected type *string", give, got) + } + + // passing struct by value should return pointer to (copy of the) struct + giveObj := testStruct{ + test: "value", + } + gotStruct := ToPointer(giveObj) + if _, ok := gotStruct.(*testStruct); !ok { + t.Errorf("ToPointer(%q) returned %q, expected type *testStruct", giveObj, gotStruct) + } + + // passing pointer should return the original pointer + ptr := &giveObj + gotPointer := ToPointer(ptr) + if gotPointer != ptr { + t.Errorf("ToPointer(%q) returned %q, expected %q", ptr, gotPointer, ptr) + } + + // passing nil should return nil back without panicking + gotNil := ToPointer(nil) + if gotNil != nil { + t.Errorf("ToPointer(%v) returned %q, expected nil", nil, gotNil) + } + + // passing number should return pointer to number + giveNumber := int64(0) + gotNumber := ToPointer(giveNumber) + if v, ok := gotNumber.(*int64); !ok { + t.Errorf("ToPointer(%q) returned %q, expected type *int64", giveNumber, gotNumber) + if *v != 0 { + t.Errorf("ToPointer(%q) returned %q, expected 0", giveNumber, gotNumber) + } + } +}