英文:
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)
}
看这个,它可以成功运行。
但是当我将
var (
config = &Config{
App: &AppConfig{},
}
)
改为
var (
config = &Config{}
)
它会失败,并显示错误信息:#panic: runtime error: invalid memory address or nil pointer dereference#
我该如何使其成功运行?
英文:
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{}
)
答案1
得分: 1
给定 f := v.Field(i)
,其中 f
表示一个指针类型,你首先需要检查 f
表示的值是否不为 nil
,在反射包中有一个方法可以做到这一点。如果返回的是 true
,即它是 nil
,那么在调用该字段的方法之前,你需要初始化该字段,使其不再是 nil
。即 f.Set(reflect.New(f.Type().Elem()))
。
你还需要确保 f
是可寻址的,为此,将指向配置的指针传递给反射,即 *Config
,而不是 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
英文:
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)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论