英文:
Type cast custom types to base types
问题
如何将自定义类型转换为interface{}
,然后再转换为基本类型(例如uint8
)?
我不能像uint16(val.(Year))
这样直接进行类型转换,因为我可能不知道所有的自定义类型,但我可以在运行时确定基本类型(uint8
、uint32
等)。
有许多基于数字的自定义类型(通常用作枚举类型):
例如:
type Year uint16
type Day uint8
type Month uint8
等等...
问题是如何将interface{}
类型转换为基本类型:
package main
import "fmt"
type Year uint16
// ....
//还有许多其他基于uint8的自定义类型
func AsUint16(val interface{}) uint16 {
return val.(uint16) //FAIL: 无法将val(类型为interface{})转换为uint16类型:需要类型断言
}
func AsUint16_2(val interface{}) uint16 {
return uint16(val) //FAIL: 无法将val(类型为interface{})转换为uint16类型:需要类型断言
}
func main() {
fmt.Println(AsUint16_2(Year(2015)))
}
http://play.golang.org/p/cyAnzQ90At
英文:
How can I convert custom type to interface{}
and then to base type (ex. uint8
)?
I can't use direct cast like uint16(val.(Year))
because I may not know all custom types, but I can determinate base types (uint8
, uint32
,...) in runtime
There are many custom types (usually used as enums) based on numeric:
ex:
type Year uint16
type Day uint8
type Month uint8
and so on...
The question is about type casting from interface{}
to base types:
package main
import "fmt"
type Year uint16
// ....
//Many others custom types based on uint8
func AsUint16(val interface{}) uint16 {
return val.(uint16) //FAIL: cannot convert val (type interface {}) to type uint16: need type assertion
}
func AsUint16_2(val interface{}) uint16 {
return uint16(val) //FAIL: cannot convert val (type interface {}) to type uint16: need type assertion
}
func main() {
fmt.Println(AsUint16_2(Year(2015)))
}
答案1
得分: 16
你可以使用reflect
包来实现这个:
package main
import "fmt"
import "reflect"
type Year uint16
func AsUint16(val interface{}) uint16 {
ref := reflect.ValueOf(val)
if ref.Kind() != reflect.Uint16 {
return 0
}
return uint16(ref.Uint())
}
func main() {
fmt.Println(AsUint16(Year(2015)))
}
根据你的情况,你可能想要返回(uint16, error)
,而不是返回空值。
https://play.golang.org/p/sYm1jTCMIf
英文:
You can accomplish this by using the reflect
package:
package main
import "fmt"
import "reflect"
type Year uint16
func AsUint16(val interface{}) uint16 {
ref := reflect.ValueOf(val)
if ref.Kind() != reflect.Uint16 {
return 0
}
return uint16(ref.Uint())
}
func main() {
fmt.Println(AsUint16(Year(2015)))
}
Depending on your situation, you may want to return (uint16, error)
, instead of returning the empty value.
答案2
得分: 9
你为什么在问题中包含了Year
?你是希望将任意事物转换为年份,还是将年份转换为uint16?
如果我假设你指的是后一种情况,那么最好使用以下方法:
func (y Year) AsUint16() uint16 {
return uint16(y)
}
这个方法不需要进行任何类型断言或反射。
链接:https://play.golang.org/p/9wCQJe46PU
英文:
Why did you include Year
in the question? Are you hoping to convert arbitrary things into Years, or convert Years into uint16s?
If I assume you meant the latter case, then it would be better to use a method
func (y Year) AsUint16() uint16 {
return uint16(y)
}
which doesn't need any type assertions or reflection.
答案3
得分: 0
Go 1.18及以上版本
在引入泛型之后,现在更容易编写适用于任何定义类型的函数。
func AsUint16[T ~uint16](v T) uint16 {
return uint16(v)
}
func AsUint8[T ~uint8](v T) uint8 {
return uint8(v)
}
与interface{}
不同,这种转换是有效的,因为类型参数明确限制为具有特定底层类型的类型,使用波浪符号~
(更多信息:https://stackoverflow.com/questions/70888240/whats-the-meaning-of-the-new-tilde-token-in-go)。
缺点是您必须为每个底层类型编写不同的函数,如上面的uint16
,uint8
等。使用类型切换在函数体中可以使用联合约束,但在我看来,使用专门的函数更清晰 —— 结果是相同的。
英文:
Go 1.18 and above
After the introduction of generics, it's now easier to write such a function that works for any defined type.
func AsUint16[T ~uint16](v T) uint16 {
return uint16(v)
}
func AsUint8[T ~uint8](v T) uint8 {
return uint8(v)
}
Unlike with interface{}
, the conversion works because the type parameter is explicitly constrained to types with that specific underlying type using tilde ~
(more info: https://stackoverflow.com/questions/70888240/whats-the-meaning-of-the-new-tilde-token-in-go).
The downside is that you must write a different function for each underlying type, as shown above with uint16
, uint8
, etc. A union constraint would work with a type switch in the function body, but in my opinion it's much clearer to use specialized functions — the result is the same.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论