#go #casting #unsafe
#Вперед #Кастинг #небезопасный
Вопрос:
Мне было интересно, могу ли я реализовать менее подробную версию этой функции. Было бы здорово, если бы у него была лучшая производительность.
func AnyIntToInt(x interface{}) (int, error) {
switch val := x.(type) {
case int8:
return int(val), nil
case int16:
return int(val), nil
case int32:
return int(val), nil
case int64:
return int(val), nil
case uint8:
return int(val), nil
case uint16:
return int(val), nil
case uint32:
return int(val), nil
case uint64:
return int(val), nil
}
return 0, ErrNotInteger
}
Я пытался с этим, однако это дает неожиданные результаты.
func AnyIntToInt(x interface{}) (int, error) {
return *(*int)(unsafe.Pointer(amp;x))
}
Комментарии:
1. Нет, нет ярлыка с использованием небезопасного пакета. Код в небезопасной версии функции неправильно предполагает, что все целочисленные и беззнаковые типы имеют ту же компоновку памяти, что и an
int
.2. Я думаю, что небезопасная версия вашего кода дает неожиданные результаты, потому что она пытается переосмыслить сам интерфейс, а не значение, указанное в нем. Однако, даже если вы все правильно поняли, комментарий Cerise Limon все еще применяется
Ответ №1:
Код в вопросе — это правильный путь, но вы можете сократить строки кода, используя пакет reflect:
func AnyIntToInt(x interface{}) (int, error) {
v := reflect.ValueOf(x)
switch v.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return int(v.Int()), nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return int(v.Uint()), nil
}
return 0, ErrNotInteger
}