【问题标题】:How to type assert ad-hoc struct to concrete struct如何将断言临时结构键入具体结构
【发布时间】:2023-03-23 07:48:01
【问题描述】:

我对使用反射生成的结构和普通结构之间的类型断言有疑问。

我知道这是一个非常有限的用例,但我仍然想知道为什么它不起作用。

https://play.golang.org/p/Ko7e8ysgjCk

package main

import (
    "fmt"
    "math/big"
    "reflect"
)

type TupleT struct {
    X *big.Int
    Y *big.Int
}

func main() {
    var fields []reflect.StructField
    fields = append(fields, reflect.StructField{
        Name: "X",
        Type: reflect.TypeOf(new(big.Int)),
        //Tag:  reflect.StructTag("json:\"" + "x" + "\""),
    })
    fields = append(fields, reflect.StructField{
        Name: "Y",
        Type: reflect.TypeOf(new(big.Int)),
        //Tag:  reflect.StructTag("json:\"" + "y" + "\""),
    })
    a := reflect.New(reflect.StructOf(fields)).Elem().Interface()
    if _ = a.(TupleT); true {
        fmt.Println("Hello, playground")
    }

    b := new (struct {X *big.Int "json:\"x\""; Y *big.Int "json:\"y\""})
    interf2 := interface{}(b)
    if _ = interf2.(*TupleT); true {
        fmt.Println("Hello, playground")
    }
}

【问题讨论】:

    标签: go struct reflection


    【解决方案1】:

    因为type assertion 不是这样工作的:

    x.(T)
    

    断言x 不是nil 并且存储在x 中的值是T 类型。

    类型断言断言接口值中的类型是“完全”T。在你的情况下,这不成立。您在接口中有一个未命名的结构值,它不能与命名类型main.TupleT 相同。可能是这些类型具有相同的底层类型或者它们是可转换的,但它们并不相同,因此类型断言失败。

    如果您使用convert 使用Value.Convert() 的值,您可以做任何您想做的事情:

    a := reflect.New(reflect.StructOf(fields)).Elem().
        Convert(reflect.TypeOf(TupleT{})).Interface()
    if _, ok := a.(TupleT); ok {
        fmt.Println("Hello, playground")
    }
    

    类似地,当使用类型断言而不使用反射时,由于接口值包含一个未命名的结构类型的值,因此您必须键入断言:

    b := new(struct {
        X *big.Int `json:"x"`
        Y *big.Int `json:"x"`
    })
    interf2 := interface{}(b)
    if _, ok := interf2.(*struct {
        X *big.Int `json:"x"`
        Y *big.Int `json:"x"`
    }); ok {
        fmt.Println("Hello, playground")
    }
    

    尝试Go Playground 上的示例。

    请注意,在第二种情况下,您还必须指定结构标记,即使在第一个示例中不需要它。这是因为具有相同字段(不考虑标签)的结构可以相互转换,但它们并不相同。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多