简体   繁体   中英

GO: how can i use go reflect to set the value of pointer of struct

package main

import (
    "fmt"
    "reflect"
)

type Config struct {
    App *AppConfig
}

type AppConfig struct {
    Name string
}

func (a *AppConfig) Parse() {
    a.Name = "111"
}

var (
    config = &Config{
        App: &AppConfig{},
    }
)

func main() {

    v := reflect.ValueOf(*config)
    typeOf := reflect.TypeOf(*config)

    for i := 0; i < typeOf.NumField(); i++ {
        method := v.Field(i).MethodByName("Parse")
        method.Call([]reflect.Value{})
    }
    fmt.Println(config)
}

look at this, it can run successfully

but when i change

var (
    config = &Config{
        App: &AppConfig{},
    }
)

to

var (
    config = &Config{}
)

it will be failed with error # panic: runtime error: invalid memory address or nil pointer dereference #

how can i run successfully with

var (
    config = &Config{}
)

Given f:= v.Field(i) where f represents a pointer type, you first need to check whether the value represented by f isn't nil , there's a method for that in the reflect package. And if you get back true , ie it is nil , then, before you can call a method on that field, you need to initialize that field so that is it not nil anymore. ie f.Set(reflect.New(f.Type().Elem())) .

And you also need to make sure that the f is addressable , to do that, pass a pointer to the config to reflect, ie *Config , not Config .

v := reflect.ValueOf(config).Elem()
typeOf := reflect.TypeOf(config).Elem()

for i := 0; i < typeOf.NumField(); i++ {
    f := v.Field(i)
    if f.Kind() == reflect.Ptr && f.IsNil() {
        f.Set(reflect.New(f.Type().Elem()))
    }
    method := f.MethodByName("Parse")
    method.Call([]reflect.Value{})
}
fmt.Println(config)
fmt.Println(config.App)

https://go.dev/play/p/DMRFS41NXFS

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM