Go:在switch类型中将任何int值转换为int64

时间:2013-06-20 18:10:36

标签: casting go

我经常遇到这种情况,我希望int(任何类型,int/int8/16/32/64)并使用类型开关检查它

switch t := v.(type) {
  case int, int8, int16, int32, int64:
    // cast to int64
  case uint, uint8, uint16, uint32, uint64:
    // cast to uint64
}

现在我无法使用直接转换,因为在这种情况下t将是interface{}类型。对于每种整数类型,我真的必须将其拆分为case吗?

我知道我可以通过使用reflect.ValueOf(v).Int()的反射来做到这一点,但是不应该有更好的(不那么详细)的方式吗?

更新:

提起了一个问题,Rob建议在这种情况下使用reflect

4 个答案:

答案 0 :(得分:24)

如果没有更多的上下文,很难给你一个意见,但看起来你正试图让你的实现过于通用,这对那些主要使用更多动态语言或支持通用支持的人来说很常见。

Learning Go的部分过程是学会接受其类型系统,并且取决于你来自哪里,它可能具有挑战性。

通常,在Go中,您希望支持一种可以容纳您需要处理的所有可能值的类型。在你的情况下,它可能是一个int64。

例如,看看数学包。它只适用于int64,并期望使用它的任何人正确地对其进行类型转换,而不是试图转换所有内容。

另一种选择是使用接口与类型无关,就像排序包一样。基本上,任何特定类型的方法都将在您的包之外实现,并且您希望定义某些方法。

学习和接受这些属性需要一段时间,但总的来说,它在可维护性和稳健性方面证明是好的。接口确保您具有正交性,强类型可确保您控制类型转换,最终可能导致错误以及内存中不必要的副本。

干杯

答案 1 :(得分:13)

你想解决什么问题?您所描述的完整解决方案如下所示:

func Num64(n interface{}) interface{} {
    switch n := n.(type) {
    case int:
        return int64(n)
    case int8:
        return int64(n)
    case int16:
        return int64(n)
    case int32:
        return int64(n)
    case int64:
        return int64(n)
    case uint:
        return uint64(n)
    case uintptr:
        return uint64(n)
    case uint8:
        return uint64(n)
    case uint16:
        return uint64(n)
    case uint32:
        return uint64(n)
    case uint64:
        return uint64(n)
    }
    return nil
}

func DoNum64Things(x interface{}) {
    switch Num64(x).(type) {
    case int64:
        // do int things
    case uint64:
        // do uint things
    default:
        // do other things
    }
}

答案 2 :(得分:7)

使用reflect包。请注意,这可能比展开开关慢很多。

switch t := v.(type) {
case int, int8, int16, int32, int64:
    a := reflect.ValueOf(t).Int() // a has type int64
case uint, uint8, uint16, uint32, uint64:
    a := reflect.ValueOf(t).Uint() // a has type uint64
}

答案 3 :(得分:-2)

您可以执行以下操作...转换为字符串然后解析字符串。不是很有效但紧凑。我把这个例子放在Go操场上:http://play.golang.org/p/0MCbDfUSHO

package main

import "fmt"
import "strconv"

func Num64(n interface{}) int64 {
    s := fmt.Sprintf("%d", n)
    i,err := strconv.ParseInt(s,10,64)
    if (err != nil) {
        return 0
    } else {
        return i
    }
}

func main() {
    fmt.Println(Num64(int8(100)))
    fmt.Println(Num64(int16(10000)))
    fmt.Println(Num64(int32(100000)))
    fmt.Println(Num64(int64(10000000000)))
    fmt.Println(Num64("hello"))
}

// Outputs:
// 100
// 10000
// 100000
// 10000000000
// 0