type Client struct {
Id int
Age int
PrimaryContact Contact
Name string
}
type Contact struct {
Id int
ClientId int
IsPrimary bool
Email string
}
以上是示例代码;我想要实现的是以下内容:
- 使用反射循环遍历所有客户端结构字段
- 使用反射为每个“原始”字段设置默认值
- 对于每个结构字段使用递归来应用上述步骤
问题是,当内省(introspection) PrimaryContact 字段时,当我尝试为其任何字段设置值时,我最终会出现以下 panic :
如果我没记错的话,原因是 PrimaryContact 是按值而不是按引用传递的,所以当我在其任何字段上调用 Set 方法时,它会更改副本上的字段值,而不是实际参数上的值。我怎样才能克服这个问题?如何使用反射通过引用将 PrimaryContact 字段传递给我的方法?
最佳答案
我认为这是练习反射(reflection)的有趣练习。
两个指针:
Value.Addr()
工作解决方案:
package main
import (
"fmt"
"reflect"
"errors"
)
type Client struct {
Id int
Age int
PrimaryContact Contact
Name string
}
type Contact struct {
Id int
ClientId int
IsPrimary bool
Email string
}
func SetDefault(s interface{}) error {
return setDefaultValue(reflect.ValueOf(s))
}
func setDefaultValue(v reflect.Value) error {
if v.Kind() != reflect.Ptr {
return errors.New("Not a pointer value")
}
v = reflect.Indirect(v)
switch v.Kind() {
case reflect.Int:
v.SetInt(42)
case reflect.String:
v.SetString("Foo")
case reflect.Bool:
v.SetBool(true)
case reflect.Struct:
// Iterate over the struct fields
for i := 0; i < v.NumField(); i++ {
err := setDefaultValue(v.Field(i).Addr())
if err != nil {
return err
}
}
default:
return errors.New("Unsupported kind: " + v.Kind().String())
}
return nil
}
func main() {
a := Client{}
err := SetDefault(&a)
if err != nil {
fmt.Println("Error: ", err)
} else {
fmt.Printf("%+v\n", a)
}
}
输出:
{Id:42 Age:42 PrimaryContact:{Id:42 ClientId:42 IsPrimary:true Email:Foo} Name:Foo}
游乐场: http://play.golang.org/p/-Mpnb7o4vl
关于reflection - 通过反射传递引用嵌套结构,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25047424/