检查 Go 中结构体的类型

12

我正在尝试检查Go语言中结构体的类型。这是我能想到的最好方法。是否有更好的方法来实现,最好不需要初始化一个结构体?

package main

import (
    "fmt"
    "reflect"
)

type Test struct{
    foo int
}

func main() {
    t := Test{5}
    fmt.Println(reflect.TypeOf(t) == reflect.TypeOf(Test{}))
}

1
这是什么动机?你能使用 类型断言 吗? - user142162
3个回答

23

类型断言:

package main

import "fmt"

type Test struct {
    foo int
}

func isTest(t interface{}) bool {
    switch t.(type) {
    case Test:
        return true
    default:
        return false
    }
}

func main() {
    t := Test{5}
    fmt.Println(isTest(t))
}

Playground


更简化的版本:

_, isTest := v.(Test)

Playground


如果你想了解技术细节,可以参考语言规范


为什么这个可以工作,但是像 _, ok := t.(Test) 这样的就不行呢?它会报错 invalid type assertion: t.(Test) (non-interface type Test on left) - ollien
2
啊,我明白了。这里重要的不是类型转换,而是函数参数中的interface{}隐式转换。谢谢! - ollien

5

你可以将一个“类型化”的nil指针值传递给reflect.TypeOf(),并调用Type.Elem()来获取所指向值的类型。这不会分配或初始化类型的值(在问题上),因为只使用了nil指针值:

fmt.Println(reflect.TypeOf(t) == reflect.TypeOf((*Test)(nil)).Elem())

您可以在Go Playground上尝试它。

附注:这是一个完全重复的内容,但找不到原始内容。


抱歉,如果这是一个重复的问题。我自己找不到原始的记录。 - ollien
看起来这确实很聪明,但在我看来不如Emile提供的习惯用语。不过还是非常感谢你的回答 :) - ollien
1
@ollien 是的,类型断言更容易和更快,但你标记了问题为 [tag:reflection]。 - icza
也许我不应该这样做。我给它打上了这个标签,因为我发现关于检查类型的所有内容都使用了它。我应该删除这个标签吗?顺便说一句,我不是那个给你点踩的人。 - ollien
@ollien 不要这样想,你的解决方案使用了反射。 - icza

2
你可以将t赋值给一个空接口变量并检查其类型,而不一定需要编写一个函数来进行检查。
var i interface{} = t
v, ok := i.(Test)
//v = concrete value of Test struct
//ok = is (t) a type of the Test struct?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接