dth54864 2016-08-25 22:14 采纳率: 0%
浏览 35
已采纳

如何测试接口变量的基础类型的接口变量的类型是别名

Golang newbie here.

The short version of this question is: given an interface value which could be of an aliased type, what's the proper way to check whether it is of an underlying type?

I found that type assertion and type switch doesn't work.

For example, in the following program, I have a bunch of automatically generated named types Alias<N> from an underlying type Origin. And I have an interface variable v, which could be of any type. I'd like to use its Field value if v is of type Origin.

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
", v.Field)
    case Alias2:
        fmt.Printf("No... Alias2 Value: %v
", v.Field)
    default:
        fmt.Printf("No... Alias3 Value: %T
", v.(Origin).Field)
    }
}

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

Output as shown in https://play.golang.org/p/3WjpX6NcfF:

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

What would be the correct way? (I cannot list all aliased types of Origin in f since those aliased types are automatically generated and scattered around.) Any help is highly appreciated. Thanks in advance!

===== Edit 1 =====

Tried to use the reflect package, but still don't have the solution: 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
", v.(Origin).Field)

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

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

    }
}

func main() {
    g(Alias1{Field: 10})
}
  • 写回答

1条回答 默认 最新

  • dpge74512 2016-08-26 00:05
    关注

    The shortest I can get is this:

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

    (instead of third fmt in your code)

    It converts v to origin type using reflection. But then to use type assertion, but that will be reflect.Value. To cast it to type Origin, it needs to be converted to interface{} and then it can be type asserted to Origin type.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 鼠标右键,撤销删除 复制 移动,要怎样删除
  • ¥15 使用MATLAB进行余弦相似度计算加速
  • ¥15 服务器安装php5.6版本
  • ¥15 我想用51单片机和数码管做一个从0开始的计数表 我写了一串代码 但是放到单片机里面数码管只闪烁一下然后熄灭
  • ¥20 系统工程中,状态空间模型中状态方程的应用。请猛男来完整讲一下下面所有问题
  • ¥15 我想在WPF的Model Code中获取ViewModel Code中的一个参数
  • ¥15 arcgis处理土地利用道路 建筑 林地分类
  • ¥20 使用visual studio 工具用C++语音,调用openslsx库读取excel文件的sheet问题
  • ¥100 寻会做云闪付tn转h5支付链接的技术
  • ¥15 DockerSwarm跨节点无法访问问题