如何惯用地检查接口是 Go 中的两种类型之一

How to idiomatically check that an interface is one of two types in Go

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

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

intfloat64 和 return 默认情况下出错的情况下,我是否应该使用 switch 语句而不执行任何操作?这对我来说似乎很奇怪,因为那些箱子都是空的。

例如

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
}

理想情况下,您的 BoardInterface 应该包含您想要使用 i 的所有行为,这样您就可以通过 [=] 中列出的方法与 i 进行“交互” 11=]。这样,i 中包含的具体类型应该无关紧要。如果编译器允许传递一个值,你保证它实现 BoardInterface.

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

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

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