首页 > 解决方案 > 如何惯用地检查接口是否是 Go 中的两种类型之一

问题描述

假设我有一个接受非常广泛的接口的函数,它可以包装(?)或描述许多不同的类型,例如int64float64string以及其他接口。但是,此特定函数只想与浮点数和整数进行交互,并且会为任何其他底层具体类型返回错误。

在 Go 中执行此操作的惯用方法是什么?

我应该使用 switch 语句并且在它是的情况下什么都不做,int还是float64在默认情况下返回错误?这对我来说似乎很奇怪,因为这些案例只是空的。

例如

type BoardInterface interface{
    doThing()
}

type customInt int
type customFloat float64
func (i customInt) doThing() {}
func (f customFloat) doThing() {}
// Other methods for different types here...

func getThing(i BoardInterface) error {

    // i could be string, int, float, customInterface1, customInterface2...
    // but we want to assert that it is int or float.
    switch t := i.(type) {
    case customInt:
        // Do nothing here?
    case customFloat:
        // Do nothing here?
    default:
        return fmt.Errorf("Got %v want float or int", t)
    }

    // Do something with i here now that we know
    // it is a float or int.
    i.doThing()

    return nil
}

标签: gotypesinterface

解决方案


理想情况下,您BoardInterface应该包含您想要使用i的所有行为,这样您就可以i通过BoardInterface. 这样,包裹在什么具体类型中就无关紧要了i。如果编译器允许传递一个值,你就可以保证它实现了BoardInterface.

如果由于某种原因不可行(或不可能),您提出的解决方案很好。您可以通过在 simple 中列出所有允许的类型来简化它case,并且无需声明t,您可以i像这样使用:

switch i.(type) {
case customInt, customFloat:
default:
    return fmt.Errorf("Got %T want customInt or customFloat", i)
}

(注意我%T在错误消息中使用了,因为在这种情况下提供的信息更多。)


推荐阅读