mardi 15 janvier 2019

golang: using reflect to set struct field when passed in via interface{}

package main

import (
    "encoding/json"
    "os"
    "reflect"
)

func assert(err error) {
    if err != nil {
        panic(err)
    }
}

type Object struct {
    ID string
}

func test1(obj interface{}) {
    v := reflect.ValueOf(obj)
    id := v.FieldByName("ID")
    id.SetString("TEST")
    json.NewEncoder(os.Stdout).Encode(obj)
}

func test2(obj Object) {
    v := reflect.ValueOf(&obj)
    id := v.Elem().FieldByName("ID")
    id.SetString("TEST")
    json.NewEncoder(os.Stdout).Encode(obj)
}

func test3(obj interface{}) {
    v := reflect.ValueOf(&obj)
    id := v.Elem().FieldByName("ID")
    id.SetString("TEST")
    json.NewEncoder(os.Stdout).Encode(obj)
}

func main() {
    test1(Object{ID: "test"})
    test2(Object{ID: "test"})
    test3(Object{ID: "test"})
}

In the code above, only test2() works. test1() will panic with reflect: reflect.Value.SetString using unaddressable value, and test3() will panic with reflect: call of reflect.Value.FieldByName on interface Value.

My requirement is that the function MUST accept an interface{} argument, because the argument type is not fixed. All that can be fixed is that the argument will be a struct with ID field (which is a string).

How can I achieve this via reflect? Thanks!





Aucun commentaire:

Enregistrer un commentaire