【问题标题】:How to test an interface variable's underlying type if the interface variable's type is an alias如果接口变量的类型是别名,如何测试接口变量的基础类型
【发布时间】:2017-01-02 11:48:48
【问题描述】:

Golang 新手在这里。

这个问题的简短版本是:给定一个可能是别名类型的接口值,检查它是否属于底层类型的正确方法是什么?

我发现类型断言和类型切换不起作用。

例如,在下面的程序中,我有一堆从基础类型Origin 自动生成的命名类型Alias<N>。我有一个接口变量v,它可以是任何类型。如果v 的类型为Origin,我想使用它的Field 值。

package main

import (
    "fmt"
)

type Origin struct {
    Field int
}

type Alias1 Origin
type Alias2 Origin
type Alias3 Origin

// A bunch of other aliases

func f(v interface{}) {
    if _, ok := v.(Origin); ok {
        fmt.Println("type assertion works")
    }

    switch v := v.(type) {
    case Origin:
        fmt.Println("type switch works")
    case Alias1:
        fmt.Printf("No... Alias1 Value: %v\n", v.Field)
    case Alias2:
        fmt.Printf("No... Alias2 Value: %v\n", v.Field)
    default:
        fmt.Printf("No... Alias3 Value: %T\n", v.(Origin).Field)
    }
}

func main() {
    f(Alias1{Field: 10})
    f(Alias2{Field: 10})
    f(Alias3{Field: 10})
}

输出如https://play.golang.org/p/3WjpX6NcfF:

No... Alias1 Value: 10
No... Alias2 Value: 10
panic: interface conversion: interface is main.Alias3, not main.Origin

正确的方法是什么? (我无法在f 中列出Origin 的所有别名类型,因为这些别名类型是自动生成并分散在各处的。)非常感谢任何帮助。提前致谢!

===== 编辑 1 =====

尝试使用reflect 包,但仍然没有解决方案:https://play.golang.org/p/3LtG9ZOkQd

package main

import (
    "fmt"
    "reflect"
)

type Origin struct {
    Field int
}

type Alias1 Origin

// A bunch of other aliases

func g(v interface{}) {
    vt := reflect.TypeOf(v)
    ot := reflect.TypeOf(Origin{})
    if vt.ConvertibleTo(ot) {
        fmt.Printf("%T is convertible to Origin", v)

        // panic: interface is main.Alias3, not main.Origin
        // fmt.Printf("Value: %v\n", v.(Origin).Field)

        // error: vt is not a type
        // fmt.Printf("Value: %v\n", v.(vt).Field)

        // error: cannot convert v (type interface {}) to type Origin: need type assertion
        // fmt.Printf("Value: %v\n", Origin(v).Field)

    }
}

func main() {
    g(Alias1{Field: 10})
}

【问题讨论】:

  • 只是想 - 可能是逐个字段比较? orig 和 alias 类型的字段集似乎相等play.golang.org/p/TY5eMrN4m9
  • @shibormot 嗯,这似乎并没有什么帮助,因为我仍然不能“使用”v(接口值)作为Origin 类型。即使v 的类型与Origin 具有相同的字段,编译器也不允许我将v 转换为Origin
  • reflect.ValueOf 和 reflect.Convert 是你的朋友play.golang.org/p/dspem2VnA7
  • 但是你想要达到的目标毫无意义。看起来您想为结构和“别名”添加行为 - 使用 GetField 和 SetField 方法定义接口。
  • Comparing with a private interface 的相关/可能重复。

标签: go types interface


【解决方案1】:

我能得到的最短的是:

fmt.Printf("Value: %v\n", reflect.ValueOf(v).Convert(ot).Interface().(Origin).Field)

(而不是代码中的第三个 fmt)

它使用反射将 v 转换为原始类型。但随后要使用类型断言,但那将是reflect.Value。要将其转换为 Origin 类型,需要将其转换为 interface{},然后才能将其类型断言为 Origin 类型。

【讨论】:

  • 酷!这就是我一直在寻找的!实际上,我已经尝试过的只是几个向下滚动。还是谢谢!
猜你喜欢
  • 1970-01-01
  • 2018-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-29
  • 2022-01-18
相关资源
最近更新 更多