Тип литых пользовательских типов для базовых типов
Как преобразовать пользовательский тип в interface{}
, а затем в базовый тип (например, uint8
)?
Я не могу использовать прямой листинг, например uint16(val.(Year))
, потому что я могу не знать все пользовательские типы, но я могу определять базовые типы (uint8
, uint32
,...) во время выполнения
Существует множество настраиваемых типов (обычно используемых как перечисление) на основе числовых:
Пример:
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
Ответы
Ответ 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