【问题标题】:Type cast custom types to base types将自定义类型类型转换为基本类型
【发布时间】:2017-07-22 16:17:59
【问题描述】:

如何将自定义类型转换为interface{},然后再转换为基本类型(例如uint8)?

我不能像 uint16(val.(Year)) 这样使用直接强制转换,因为我可能不知道所有自定义类型,但我可以在运行时确定基本类型(uint8uint32、...)


有很多基于数字的自定义类型(通常用作枚举):

例如:

type Year  uint16
type Day   uint8
type Month uint8

等等……

问题是关于从interface{} 到基本类型的类型转换:

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

http://play.golang.org/p/cyAnzQ90At

【问题讨论】:

  • 请注意,val.(unit16)uint16(val) 都不是“强制转换”:第一个是“类型断言”,第二个是“类型转换”。

标签: go


【解决方案1】:

您可以使用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

【讨论】:

    【解决方案2】:

    您为什么在问题中包含Year?您是希望将任意事物转换为 Years,还是将 Years 转换为 uint16s?

    如果我假设你的意思是后一种情况,那么最好使用方法

    func (y Year) AsUint16() uint16 { 
        return uint16(y)
    }
    

    不需要任何类型断言或反射。

    https://play.golang.org/p/9wCQJe46PU

    【讨论】:

    • 我有很多(N)个基于简单类型(uint8、16、32...)的自定义类型。而且我不想创建 N 个方法而不是一个
    • 这很公平,但值得权衡每种方法的利弊。我上面描述的显式方法简单、快速且类型安全,但可能过于冗长。反思性方法对前来阅读您代码的人的作用会更慢,也更不明确。
    • FWIW,我已经通过使用 Gen 从模板创建样板代码来处理类似的情况,但在您的情况下,这不是一个令人信服的选择。
    猜你喜欢
    • 2019-11-06
    • 2022-01-22
    • 1970-01-01
    • 2020-10-22
    • 1970-01-01
    • 2019-05-17
    • 1970-01-01
    • 1970-01-01
    • 2016-11-16
    相关资源
    最近更新 更多