Есть ли способ реализовать эту функцию целочисленного приведения с небезопасным указателем в golang?

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

https://go.dev/play/p/gJ4ASo7AeyN