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

huangapple go评论69阅读模式
英文:

Go: cast any int value to int64 in type switch

问题

我经常遇到这样的情况,我期望一个int(任何类型的int/int8/16/32/64),并使用类型切换进行检查。

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

现在我不能直接转换,因为在这种情况下,t的类型将是interface{}。我真的需要将其拆分为每种整数类型的case吗?

我知道我可以使用反射来使用reflect.ValueOf(v).Int()来实现,但是难道没有更好(更简洁)的方法吗?

更新:

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

英文:

I often have a situation, where I expect an int (of any type, int/int8/16/32/64) and check for it using a type switch

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

Now I cannot use a direct cast, because t in this case will be of type interface{}. Do I really have to split this up into cases for each integer type?

I know that I could do it via reflection using reflect.ValueOf(v).Int(), but shouldn't there be a better (less verbose) way of doing this?

UPDATE:

Filed an issue, and Rob advised to just use reflect in this case.

答案1

得分: 24

没有更多的上下文很难给你一个意见,但是看起来你试图使你的实现过于通用,这在大多数与更动态的语言或具有通用支持的语言工作的人中很常见。

学习Go的过程中,一部分是学会接受它的类型系统,根据你来自哪里,这可能是具有挑战性的。

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

例如,看看math包。它只使用int64,并期望任何使用它的人正确地进行类型转换,而不是尝试转换一切。

另一个选择是使用接口来实现类型不可知性,就像sort包一样。基本上,任何特定于类型的方法都将在你的包之外实现,并且你期望定义某些方法。

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

干杯

英文:

It's hard to give you an opinion without more context but it looks like you're trying to make your implementation too generic, which is common from people that worked mostly with more dynamic languages or w/ generic support.

Part of the process of Learning Go is learning to embrace its type system, and depending on where you're coming from, it can be challenging.

Usually, in Go, you want to support one type that can hold all possible values you need to handle. In your case it would probably be a int64.

Take a look on the math package, for example. It only work with int64 and expect anyone using it to typecast it properly instead of trying to convert everything.

Another option is to use a interface to be type-agnostic, like the sort package does. Basically, any method that are type specific will be implemented outside of your package and you expect certain methods to be defined.

It takes a while to learn and accept these attributes but overall, in the end, it proves to be good in terms of maintainability and robustness. Interfaces ensure you have orthogonality and strong types makes sure you're in control of type conversions, which in the end can cause bugs and also unnecessary copies in memory.

Cheers

答案2

得分: 14

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
}
}

英文:

What problem are you trying to solve? The full solution that you've described looks like this:

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
	}
}

答案3

得分: 8

使用reflect包。请注意,这可能比展开switch语句要慢得多。

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

Use the reflect package. Notice that this is likely to be a lot slower than unrolling the switch.

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
}

答案4

得分: -1

你可以这样做...将其转换为字符串,然后解析字符串。虽然不是很高效,但很简洁。我在Go playground中放了这个例子: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"))
}

// 输出:
// 100
// 10000
// 100000
// 10000000000
// 0
英文:

You could do something like this... convert to a string and then parse the string. Not really efficient but compact. I've put this example in the Go playground here: 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

huangapple
  • 本文由 发表于 2013年6月21日 02:10:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/17220764.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定