gpt4 book ai didi

go - 使用反射填充指向结构的指针

转载 作者:数据小太阳 更新时间:2023-10-29 03:08:12 25 4
gpt4 key购买 nike

我想遍历结构中的字段并提示将字符串值输入字符串字段,对作为结构指针的字段递归执行此操作。

目前这是我尝试过的方法,但在尝试在指针的字符串字段中设置此值时出现错误。

package main

import (
"fmt"
"reflect"
)

type Table struct {
PK *Field
}

type Field struct {
Name string
}


func main() {
PopulateStruct(&Table{})
}

func PopulateStruct(a interface{}) interface {} {
typeOf := reflect.TypeOf(a)
valueOf := reflect.ValueOf(a)
for i := 0; i < typeOf.Elem().NumField(); i++ {
switch typeOf.Elem().Field(i).Type.Kind() {
case reflect.String:
fmt.Print(typeOf.Elem().Field(i).Name)
var s string
fmt.Scanf("%s", &s)
valueOf.Elem().Field(i).SetString(s)
case reflect.Ptr:
ptr := reflect.New(valueOf.Elem().Field(i).Type())
PopulateStruct(ptr.Elem().Interface())
valueOf.Elem().Field(i).Set(ptr)
}
}
}

期望返回值包含一个初始化的结构,并设置了指针字符串字段。

设置指针的字符串字段时出错。

panic :反射(reflect):在零值上调用 reflect.Value.Field

最佳答案

我将你的代码按原样放到了 Go Playground 中,但它没有构建,因为 PopulateStruct声明为返回 interface{}但实际上并没有返回任何东西。删除声明的返回类型会产生您提到的 panic 。

这是因为在进入外部PopulateStruct调用,你有一个有效的指针,指向一个零值 Table .零值 Table有一个元素:其中有一个 *Field 类型的 nil 指针.因此,您的循环运行一次并找到一个 reflect.Ptr ,如你所料。添加更多诊断打印消息有助于了解发生了什么:

fmt.Printf("PopulateStruct: I have typeOf=%v, valueOf=%v\n", typeOf, valueOf)
for i := 0; i < typeOf.Elem().NumField(); i++ {
switch typeOf.Elem().Field(i).Type.Kind() {
// ... snipped some code ...
case reflect.Ptr:
ptr := reflect.New(valueOf.Elem().Field(i).Type())
fmt.Println("after allocating ptr, we have:", ptr.Type(), ptr,
"but its Elem is:", ptr.Elem().Type(), ptr.Elem())

这打印:

PopulateStruct: I have typeOf=*main.Table, valueOf=&{<nil>}
after allocating ptr, we have: **main.Field 0x40c138 but its Elem is: *main.Field <nil>

给定方式PopulateStruct本身构造,我们实际上必须分配一个真正的Field 现在实例,在调用PopulateStruct之前.我们可以这样做:

        p2 := ptr.Elem()
ptr.Elem().Set(reflect.New(p2.Type().Elem()))

(code borrowed from json.Unmarshal )。现在我们可以填写这个 Field , 其中有一个字段名为 Name类型 String .

在我看来,这里的整体策略不是很好:填充可能应该采用通用指针,而不是专门指向- struct 的指针。指针。然后您可以模拟 indirect json 解码器中的函数。但是,添加这两行——创建目标对象并使分配的指针指向它——足以让您现有的代码运行。

(或者,您可以只从头开始创建并返回整个实例,在这种情况下,您只需要类型——但我假设您有一个模式,其中只有一些字段是无。)

Here's the complete Go Playground example.我做了一些其他更改,因为在使用 playground 时没有什么可扫描的。

关于go - 使用反射填充指向结构的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57465920/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com