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

是否可以确定(使用)任意类型的实例是否可以设置为任意值,即确定是否由于类型不兼容而导致死机?reflectValue.Set()


MCVE如下所述。我想知道的是有效的“我可以在不使用延迟/恢复构造的情况下编写吗?set()


我想避免不仅因为它看起来很丑陋,而且因为可能因为其他原因而恐慌。deferValue.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())


}


元芳怎么了
浏览 119回答 1
1回答

30秒到达战场

反映。类型有一个方法: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)将会死机。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go