【发布时间】:2021-04-10 05:12:06
【问题描述】:
是否可以确定(使用reflect)是否可以将任意类型的实例设置为任意值,即确定Value.Set() 是否会由于类型不兼容而出现恐慌?
下面列出了一个 MCVE。我想知道的是“我可以在不使用延迟/恢复结构的情况下编写set() 吗?”
我想避免 defer 不仅因为它看起来很丑,而且因为 Value.Set() 可能会因为其他原因而恐慌。
请注意,这不只是比较类型是否相等的问题,如下面的o2 示例所示。
package main
import (
"fmt"
"reflect"
)
// set a value V to interface i, returning true if this can be done, else false
//
// CAN WE WRITE THIS WITHOUT HAVING TO USE DEFER / RECOVER?
//
func set(v reflect.Value, i interface{}) bool {
success := true
defer func() {
if r := recover(); r != nil {
success = false
}
}()
v.Set(reflect.ValueOf(i))
return success
}
// get the type of a typed nil
func getType(typedNil interface{}) reflect.Type {
return reflect.TypeOf(typedNil).Elem()
}
func main() {
t1 := getType((*int)(nil))
o1 := reflect.New(t1)
t2 := getType((*interface{})(nil))
o2 := reflect.New(t2)
var ok bool
var aInt = 456
var aString string = "hello"
var aUint uint = 123
// Set o1 to various types
ok = set(o1.Elem(), aInt) // Should return true
fmt.Printf("After o1 set to aInt returned %v: obj is type %T content '%v'\n", ok, o1.Elem().Interface(), o1.Elem().Interface())
ok = set(o1.Elem(), aString) // Should return false
fmt.Printf("After o1 set to aString returned %v: obj is type %T content '%v'\n", ok, o1.Elem().Interface(), o1.Elem().Interface())
ok = set(o1.Elem(), aUint) // Should return false
fmt.Printf("After o1 set to aUint returned %v: obj is type %T content '%v'\n", ok, o1.Elem().Interface(), o1.Elem().Interface())
fmt.Println("")
// Set o2 to various types
ok = set(o2.Elem(), aInt) // Should return true
fmt.Printf("After o2 set to aInt returned %v: obj is type %T content '%v'\n", ok, o2.Elem().Interface(), o2.Elem().Interface())
ok = set(o2.Elem(), aString) // Should return true
fmt.Printf("After o2 set to aString returned %v: obj is type %T content '%v'\n", ok, o2.Elem().Interface(), o2.Elem().Interface())
ok = set(o2.Elem(), aUint) // Should return true
fmt.Printf("After o2 set to aUint returned %v: obj is type %T content '%v'\n", ok, o2.Elem().Interface(), o2.Elem().Interface())
}
【问题讨论】:
标签: go reflection