Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
464 views
in Technique[技术] by (71.8m points)

go - Return a generic empty object clone using reflection

I need an empty copy of an object in Go, without knowing its type directly. This code will succesfully return an object as a pointer to the type. However, I don't seem to be able to just get the pointer value after that.

Trying to get this right, but getting hung up on being a value type. I can make the pointer thing work for my situation, but want to understand why it seems so hard to get the value.


package watch

import "reflect"

type TestStruct struct {
    Name string
    Data string
}

func TestClone(t *testing.T) {
    var obj TestStruct
    obj.Name = "test case"
    gotPtr := cloneEmptyObject(obj)
    got := *gotPtr.(*TestStruct)
    print(got.Name)
}

// This works but returns me a pointer, and I can cast if I explicitly have the type
func cloneEmptyObject(obj interface{}) interface{} {

    vesselObjPtr := reflect.New(reflect.TypeOf(obj)).Interface()
    // want to do the equivalent of this without explicitly having type TestStruct:
    // return *vesselObjPtr.(*TestStruct) 
    return vesselObjPtr
}

func TestClone2(t *testing.T) {
    var obj TestStruct
    obj.Name = "test case"
    got := cloneEmptyObject2(obj)
    b:= got.(TestStruct) //This fails and causes a panic
    print(b.Name)
}

//want this where I don't explicitly need the Type to get the value
func cloneEmptyObject2(obj interface{}) interface{} {

    vesselObjPtr := reflect.New(reflect.TypeOf(obj))
    // return *vesselObjPtr //invalid indirect of vesselObjPtr (type "reflect".Value)
    vesselObj := reflect.Indirect(vesselObjPtr)
    return vesselObj // want this to be TestStruct, but it is a reflect.Value, and can't be cast
}

func TestClone3(t *testing.T) {
    var obj TestStruct
    obj.Name = "test case"
    got := cloneEmptyObject3(obj)
    b:= got.(TestStruct)
    print(b.Name)
}

func cloneEmptyObject3(obj interface{}) interface{} {
    return reflect.Zero(reflect.TypeOf(obj))
}

func TestClone4(t *testing.T) {
    var obj TestStruct
    obj.Name = "test case"
    got := cloneEmptyObject4(obj)
    b:= got.(TestStruct)
    print(b.Name)
}

func cloneEmptyObject4(obj interface{}) interface{} {
    return reflect.New(reflect.TypeOf(obj)).Elem()
}

Not trying to be dense, but this seems to be the suggestion, from comments, and it simply doesn't compile

func TestClone5(t *testing.T) {
    var obj TestStruct
    obj.Name = "test case"
    got := cloneEmptyObject5(obj)
    b:= got.(TestStruct)
    print(b.Name)
}

func cloneEmptyObject5(obj interface{}) interface{} {

    vesselObjPtr := reflect.New(reflect.TypeOf(obj)).Interface()
    // vesselObj := reflect.Indirect(vesselObjPtr)
    //cannot use vesselObjPtr (type interface {}) as type "reflect".Value in argument to "reflect".Indirect: need type assertion
    //return vesselObj
}
=== RUN   TestClone
--- PASS: TestClone (0.00s)
=== RUN   TestClone2
--- FAIL: TestClone2 (0.00s)
panic: interface conversion: interface {} is reflect.Value, not watch.TestStruct [recovered]
    panic: interface conversion: interface {} is reflect.Value, not watch.TestStruct
=== RUN   TestClone3
--- FAIL: TestClone3 (0.00s)
panic: interface conversion: interface {} is reflect.Value, not watch.TestStruct [recovered]

=== RUN   TestClone4
--- FAIL: TestClone4 (0.00s)
panic: interface conversion: interface {} is reflect.Value, not watch.TestStruct [recovered]
    panic: interface conversion: interface {} is reflect.Value, not watch.TestStruct




与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...