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

Time:08-25

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{}
)

CodePudding user response:

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, i.e. 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. i.e. 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, i.e. *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

  • Related