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)