mardi 24 octobre 2017

Generically set value of field on any struct

I would like to be able to create a function which can accept any struct as an argument and set the first field of that struct to a certain value (my actually use case is different but this was a minimal example which exhibited the problem).

Here is my attempt so far: go playground link

 package main

 import (
    "fmt"
    "reflect"
 )

 type A struct {
    X string
 }

 // this works
 func modifyFieldsForA(v A) interface{} {
    f := reflect.ValueOf(&v).Elem()
    f.Field(0).SetString("Modified")
    return f.Interface()
 }


 type B struct {
    Y string
    Z string
 }

 // this gives an error "reflect: call of reflect.Value.Field on interface Value"
 func modifyFieldsGeneric(v interface{}) interface{} {
    f := reflect.ValueOf(&v).Elem()
    f.Field(0).SetString("Modified")
    return f.Interface()
 }

 func main() {
    a := A{"hello"}
    a2 := modifyFieldsForA(a)
    fmt.Printf("New a: %+v\n", a2)
    a2 = modifyFieldsGeneric(a)
    fmt.Printf("New a: %+v\n", a2)

    b := B{"hello", "word"}
    b2 := modifyFieldsGeneric(b)
    fmt.Printf("New b: %+v", b2)
 }

The first function which acts only on structs of type A works fine. The second one does not. I think because the reflection library does not necessarily know I'm definitely going to give it a struct rather than an instance of any interface. Is there a way to get the generic function to work?

Thanks!





Aucun commentaire:

Enregistrer un commentaire