首页 > 解决方案 > 打开没有类型断言的接口类型

问题描述

我有一个可以采用多种不同参数类型的函数。我想使用类型开关并尽可能减少代码重复。作为一个非常基本的示例,在这里我想将uint8int8类型都复制到字节缓冲区中。这段代码很高兴地工作

package main

func switchFn(args ...interface{}) {
    var buf []byte
    for _, arg := range args {
        switch val := arg.(type) {
        case uint8:
            buf = append(buf, byte(val))
        case int8:
            buf = append(buf, byte(val))
        }
    }
}

func main() {
    switchFn(int8(42), uint8(42)) // etc
}

您会注意到两个 case 语句的作用完全相同!如果我把它们结合起来......

package main

func switchFn(args ...interface{}) {
    var buf []byte
    for _, arg := range args {
        switch val := arg.(type) {
        case uint8, int8:
            buf = append(buf, byte(val))
        }
    }
}

func main() {
    switchFn(int8(42), uint8(42)) // etc
}

我遇到了一个问题cannot convert val (type interface {}) to type byte: need type assertion。但我实际上是在切换类型!啊!

我是否坚持这里的代码重复,还是有更聪明的方法来做到这一点?请注意,复制到字节缓冲区用于说明示例,我的函数可能在案例块中做其他事情。

标签: goswitch-statement

解决方案


这是一种避免代码重复的方法,代价是......好吧,另一种代码重复:

func switchFn(args ...interface{}) {
    var buf []byte
    for _, arg := range args {
        var val byte
        switch v := arg.(type) {
        case uint8:
            val = byte(v)
        case int8:
            val = byte(v)
        default:
            panic("wrong type")
        }
        buf = append(buf, val)
    }
}

对于这个特定的功能,原始副本可能更好。如果该buf = append(buf, val)部分变得更大或更复杂,这可能会更好。

在其他情况下——也许是最真实的情况——gopher 建议的方法可能是最好的:

    f := func(val byte) {
        buffer = append(buffer, val)
    }

您现在可以f从每个case.


推荐阅读