Отличие uint от int?go-23
Основные различия
1. Диапазон значений
int - знаковое целое число:
var i int = -42 // Может быть отрицательным
uint - беззнаковое целое число:
var u uint = 42 // Только положительные значения
2. Размер в памяти
Размер обоих типов зависит от платформы:
- 32-битные системы: 32 бита (4 байта)
- 64-битные системы: 64 бита (8 байта)
Но диапазоны отличаются: |
Тип |
32-битный диапазон |
64-битный диапазон |
int |
-2³¹ до 2³¹-1 (-2.1B до 2.1B) |
-2⁶³ до 2⁶³-1 |
uint |
0 до 2³²-1 (0 до 4.2B) |
0 до 2⁶⁴-1 |
3. Использование в операциях
Проблема смешивания типов:
var i int = -5
var u uint = 10
sum := i + u // Ошибка компиляции!
Требуется явное приведение:
sum := i + int(u) // Корректно
4. Переполнение
int при переполнении "заворачивается" в отрицательные:
var i int = math.MaxInt
i++ // Станет math.MinInt
uint при переполнении "заворачивается" в 0:
var u uint = math.MaxUint
u++ // Станет 0
Когда что использовать
Используйте uint для:
- Битовых операций
- Индексов, когда отрицательные значения невозможны
- Работы с бинарными данными
- Системного программирования (адреса памяти)
Пример:
func countBits(n uint) int {
count := 0
for n != 0 {
count++
n &= n - 1
}
return count
}
Используйте int для:
- Математических операций, где возможны отрицательные числа
- Индексов в большинстве случаев (идиоматично для Go)
- Общих вычислений
Пример:
func abs(n int) int {
if n < 0 {
return -n
}
return n
}
Особенности производительности
- На большинстве современных процессоров нет разницы в скорости
- В некоторых случаях uint может быть быстрее для битовых операций
- int обычно предпочтительнее для индексов (даже когда uint логичнее)
Подводные камни
- Неожиданные результаты при приведении отрицательных int к uint:
i := -1
u := uint(i) // 18446744073709551615 (на 64-бит)
- Сравнения между разными типами требуют осторожности:
if uint(-1) > 0 { // Всегда true!
fmt.Println("Unexpected!")
}
- JSON unmarshalling может вести себя по-разному для uint и int.
Резюмируем
- int - знаковый целочисленный тип, uint - беззнаковый
- Оба имеют платформозависимый размер (32/64 бита)
- uint не может хранить отрицательные значения
- Смешивание типов требует явного приведения
- Переполнение обрабатывается по-разному
- int идиоматичнее для большинства случаев в Go
- uint полезен для битовых операций и низкоуровневых задач
- Требуется осторожность при преобразованиях и сравнениях
Правила выбора:
- По умолчанию используйте int
- Для битовых операций и индексов без отрицательных значений - uint
- Избегайте смешивания в выражениях без явного приведения