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 乌班图ip地址配置及远程SSH
  • ¥15 怎么让点阵屏显示静态爱心,用keiluVision5写出让点阵屏显示静态爱心的代码,越快越好
  • ¥15 PSPICE制作一个加法器
  • ¥15 javaweb项目无法正常跳转
  • ¥15 VMBox虚拟机无法访问
  • ¥15 skd显示找不到头文件
  • ¥15 机器视觉中图片中长度与真实长度的关系
  • ¥15 fastreport table 怎么只让每页的最下面和最顶部有横线
  • ¥15 java 的protected权限 ,问题在注释里
  • ¥15 这个是哪里有问题啊?