Golang中reflect.Value.Set使用不可寻址值的解决方法
Golang中reflect.Value.Set使用不可寻址值的解决方法
我正在尝试创建一个 struct 并为其附加 字段 和 方法/函数,因此我以以下代码开始:
package main
import (
"reflect"
)
func main() {
s := reflect.Zero(reflect.TypeOf(reflect.Struct))
f := reflect.Zero(reflect.TypeOf(reflect.StructField{
Name: "id",
PkgPath: "",
Type: reflect.TypeOf(reflect.Int),
Tag: "",
Offset: 0,
Index: []int{},
Anonymous: false,
}))
m := reflect.Zero(reflect.TypeOf(reflect.Method{
Name: "add",
PkgPath: "",
Type: reflect.TypeOf(reflect.FuncOf(
[]reflect.Type{reflect.TypeOf(reflect.Int)},
[]reflect.Type{reflect.TypeOf(reflect.Int)},
false)),
Func: f,
Index: 0,
}))
swap := func(in []reflect.Value) []reflect.Value {
return []reflect.Value{in[1], in[0]}
}
t := reflect.ValueOf(&swap).Elem()
m.Set(reflect.MakeFunc(t.Type(), swap))
_ = m
_ = s
}
但在 m.Set(reflect.MakeFunc(t.Type(), swap)) 这一行,我遇到了错误:
panic: reflect: reflect.Value.Set using unaddressable value
goroutine 1 [running]:
reflect.flag.mustBeAssignableSlow(0x3?)
D:/Development/go/src/reflect/value.go:262 +0x85
reflect.flag.mustBeAssignable(...)
D:/Development/go/src/reflect/value.go:249
reflect.Value.Set({0xa7ff20?, 0xb53a60?, 0xa8c208?}, {0xa78500?, 0xc00008a210?, 0xa14313?})
D:/Development/go/src/reflect/value.go:2084 +0x6a
main.main()
D:/Deployment/Reflection/add.go:35 +0x3cf
exit status 2
更多关于Golang中reflect.Value.Set使用不可寻址值的解决方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html
3 回复
遗憾的是,您无法在运行时为类型生成方法,但可以生成不带方法的结构体,然后使用其他反射函数(如 MakeFunc)来创建操作这些结构体的函数:Go Playground - The Go Programming Language
func main() {
fmt.Println("hello world")
}
更多关于Golang中reflect.Value.Set使用不可寻址值的解决方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
这是一个典型的反射中使用不可寻址值的问题。reflect.Zero() 返回的是不可寻址的值,而 Set() 方法要求目标值必须是可寻址的。
以下是修正后的代码示例:
package main
import (
"fmt"
"reflect"
)
func main() {
// 创建结构体类型
structType := reflect.StructOf([]reflect.StructField{
{
Name: "Id",
Type: reflect.TypeOf(0),
},
})
// 创建结构体实例(可寻址)
s := reflect.New(structType).Elem()
s.Field(0).SetInt(42)
// 创建方法类型
methodType := reflect.FuncOf(
[]reflect.Type{reflect.TypeOf(0)},
[]reflect.Type{reflect.TypeOf(0)},
false,
)
// 创建方法值(可寻址)
m := reflect.New(methodType).Elem()
// 创建函数实现
swap := func(in []reflect.Value) []reflect.Value {
return []reflect.Value{reflect.ValueOf(in[0].Int() + 1)}
}
// 设置方法值
m.Set(reflect.MakeFunc(methodType, swap))
// 测试方法调用
result := m.Call([]reflect.Value{reflect.ValueOf(10)})
fmt.Println("Result:", result[0].Int()) // 输出: Result: 11
// 如果需要将方法附加到结构体,可以使用接口
var iface interface{} = struct{}{}
val := reflect.ValueOf(&iface).Elem()
// 创建包含方法的接口类型
interfaceType := reflect.TypeOf((*interface {
Add(int) int
})(nil)).Elem()
// 实现接口
proxy := reflect.MakeFunc(
interfaceType.Method(0).Type,
func(args []reflect.Value) []reflect.Value {
return []reflect.Value{reflect.ValueOf(args[0].Int() + 1)}
},
)
// 创建实现接口的值
impl := reflect.New(interfaceType).Elem()
impl.Set(proxy)
// 调用接口方法
callResult := impl.Method(0).Call([]reflect.Value{reflect.ValueOf(5)})
fmt.Println("Interface result:", callResult[0].Int()) // 输出: Interface result: 6
}
关键修改点:
- 使用
reflect.New()创建可寻址的值而不是reflect.Zero() reflect.New()返回的是指针,需要调用.Elem()获取底层值- 对于方法设置,使用
reflect.MakeFunc()创建函数值 - 结构体字段和方法需要通过正确的类型定义来创建
如果需要动态创建包含方法的结构体,更常见的做法是:
package main
import (
"fmt"
"reflect"
)
func main() {
// 定义结构体类型
structType := reflect.StructOf([]reflect.StructField{
{
Name: "Value",
Type: reflect.TypeOf(0),
},
})
// 创建实例
instance := reflect.New(structType).Elem()
instance.Field(0).SetInt(100)
// 创建方法
methodType := reflect.FuncOf(
[]reflect.Type{reflect.TypeOf(0)},
[]reflect.Type{reflect.TypeOf(0)},
false,
)
method := reflect.MakeFunc(methodType, func(args []reflect.Value) []reflect.Value {
current := instance.Field(0).Int()
newValue := current + args[0].Int()
instance.Field(0).SetInt(newValue)
return []reflect.Value{reflect.ValueOf(newValue)}
})
// 使用方法
result := method.Call([]reflect.Value{reflect.ValueOf(50)})
fmt.Println("Method result:", result[0].Int()) // 输出: Method result: 150
fmt.Println("Instance value:", instance.Field(0).Int()) // 输出: Instance value: 150
}
这样就能正确创建可寻址的值并进行设置了。



