如何使用接口和反射来定义安全划分?

我想定义一个安全划分,例如:


func safeDivide(a, b interface{}) interface{} {

    if b == 0 {

        return 0

    }

    return a / b

}

显然,这个功能是行不通的。我们不能划分接口。一种解决方案是判断输入的类型并进行划分。


switch reflect.ValueOf(x).Kind() {

    case reflect.Int:

    // balabala...

不过看起来多余,我必须处理好每一个案件。


那么我是否可以使用反射来保证输入的类型?我尝试过reflect.TypeOf()但失败了。


顺便说一句,我注意到这一点:


a := uint32(0)

ifZero(a) // outputs "no"


func ifZero(a interface{}) {

    if a == 0 {

        log.Println("yes")

        return

    }

    log.Println("no")

}

这意味着 golang 本身无法处理类型问题,对吗?


墨色风雨
浏览 65回答 1
1回答

慕森王

现在您知道为什么(某些)人们想要在 Go 中使用泛型。:-)对于这种特殊情况,您最好只编写一个safeDivideInt函数:// a/b, but 0 if b == 0func safeDivideInt(a, b int64) int64 {    if b == 0 {        return 0    }    return a / b}和一个类似的safeDivideUint函数(使用uint64)...并且,如果需要的话,1个safeDivideFloat函数,例如:func safeDivideFloat(a, b float64) float64 {    // decide if you want 0/0 handled differently    // decide if you want to check for b being Inf or NaN    // etc.    if b == 0 {        return 0    }    return a / b}如果你愿意的话,然后再一次进行复杂的处理。但是:没有简单的方法可以让 Go 编译器为您调用其中之一。您可以按照您的方式编写基于接口的函数,然后对各种参数进行类型切换,但是由于您必须处理所有可能的组合,因此它会变得很长。无论如何减少,组合效应都是痛苦的。使用reflect和 它的 type-kind 接口在这里没有帮助,因为您仍然有五种int类型,五种uint类型(如果包含 则为六种类型uintptr),两种float类型和两种complex类型。(我不清楚在除法函数中允许使用 或UintptrsUnsafePointer Kind是否有任何意义。)然而,根据上下文,定义您自己的界面可能更有意义。 这是 Go Playground 上的一个工作玩具示例。我没有费心放入 Uint 和 Complex 类型。1请注意,运行时 1.0 / 0.0 是+Inf。Go规范说:浮点或复数除以零的结果未在 IEEE-754 标准之外指定;是否发生运行时恐慌是特定于实现的。但 IEEE-754 默认情况下要求 Inf 和 NaN 结果,异常是可选的,所以我认为这意味着 Go 中的默认情况下不会引发异常,也意味着“无恐慌”。算术异常(默认情况下)需要记录在“粘性”状态标志位中。...默认情况下,操作始终根据规范返回结果,而不会中断计算。例如,1/0 返回 +∞,同时还设置被零除标志位(这个默认值 ∞ 的设计目的是为了在后续操作中使用时经常返回有限结果,因此可以安全地忽略)。
打开App,查看更多内容
随时随地看视频慕课网APP