为了账号安全,请及时绑定邮箱和手机立即绑定

确定是否可以将任意类型的实例设置为任意类型的值

确定是否可以将任意类型的实例设置为任意类型的值

Go
元芳怎么了 2022-08-01 11:06:38
是否可以确定(使用)任意类型的实例是否可以设置为任意值,即确定是否由于类型不兼容而导致死机?reflectValue.Set()MCVE如下所述。我想知道的是有效的“我可以在不使用延迟/恢复构造的情况下编写吗?set()我想避免不仅因为它看起来很丑陋,而且因为可能因为其他原因而恐慌。deferValue.Set()请注意,这不仅仅是比较类型相等的问题,如下面的示例所示。o2package mainimport (    "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 nilfunc 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())}
查看完整描述

1 回答

?
30秒到达战场

TA贡献1828条经验 获得超6个赞

反映。类型有一个方法:Type.AssignableTo()


// AssignableTo reports whether a value of the type is assignable to type u.

AssignableTo(u Type) bool

因此,您可以使用它来简化您的函数:set()


func set(v reflect.Value, i interface{}) bool {

    if !reflect.TypeOf(i).AssignableTo(v.Type()) {

        return false

    }

    v.Set(reflect.ValueOf(i))

    return true

}

输出将相同(在Go Playground上尝试):


After o1 set to aInt returned true: obj is type int content '456'

After o1 set to aString returned false: obj is type int content '456'

After o1 set to aUint returned false: obj is type int content '456'


After o2 set to aInt returned true: obj is type int content '456'

After o2 set to aString returned true: obj is type string content 'hello'

After o2 set to aUint returned true: obj is type uint content '123'

您也可以(另外)调用 Value.CanSet() 来检测某些“不可设置”的情况:


可以设置报告是否可以更改 v 的值。仅当 Value 可寻址且未通过使用未导出的结构字段获取时,才能更改该值。如果 CanSet 返回 false,则调用 Set 或任何特定于类型的 setter(例如,SetBool、SetInt)将会死机。


查看完整回答
反对 回复 2022-08-01
  • 1 回答
  • 0 关注
  • 118 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号