Menu

Типы данных в Golang: int, float64, string, bool, byte, rune

Встроенные типы Go: размеры и диапазоны целых чисел, float32 и float64, bool, string, byte и rune, комплексные числа, нулевые значения и как напечатать тип значения через %T.

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

Базовые типы Go это числа, булевы значения и строки. У каждой переменной ровно один тип, зафиксированный на этапе компиляции, и Go никогда не преобразует типы за вас. %T печатает тип любого значения:

Обратите внимание: 'G' печатается как 71 с типом int32. Символ в одинарных кавычках это руна, то есть число (кодовая точка Unicode). rune это псевдоним int32 (тот же тип под вторым именем), поэтому %T сообщает int32. Точно так же byte показывается как uint8.

Целые числа

ТипРазмерДиапазон
int88 битот -128 до 127
int1616 битот -32 768 до 32 767
int3232 битапримерно от -2,1 млрд до 2,1 млрд
int6464 битапримерно от -9,2 квинтиллиона до 9,2 квинтиллиона
uint8 (byte)8 битот 0 до 255
uint1616 битот 0 до 65 535
uint3232 битаот 0 примерно до 4,3 млрд
uint6464 битаот 0 примерно до 18,4 квинтиллиона
int, uint32 или 64 битаразмер машинного слова платформы
uintptrразмер платформыхранит значение указателя, для низкоуровневого кода

По умолчанию используйте int. len() возвращает int, индексы слайсов имеют тип int, счётчики циклов тоже int. На любой 64-битной платформе int занимает 64 бита. Типы с фиксированным размером нужны, когда размер входит в контракт: int32 в бинарном формате файла, uint8 для сырых байтов, int64 для Unix-времени в наносекундах.

Не используйте беззнаковые типы для величин, которые «не могут быть отрицательными», например для количества. Вычитание ниже нуля даёт огромное число, а не отрицательное, которое можно было бы поймать.

Пределы и переполнение

В пакете math есть константа для каждого предела. Во время выполнения переполнение целочисленной арифметики молча заворачивается по кругу:

Ни паники, ни ошибки: 127 + 1 превращается в -128. На этапе компиляции проверяются только константные выражения (var b int8 = 128 не скомпилируется). Если в ваших данных переполнение возможно, проверяйте перед операцией или используйте math/big.

Целочисленные литералы

million := 1_000_000   // underscores for readability (Go 1.13+)
mask := 0xFF           // hexadecimal
perm := 0o755          // octal (also the older form 0755)
flags := 0b1010        // binary

Числа с плавающей точкой

ТипРазмерТочность
float3232 битапримерно от 6 до 9 значащих цифр
float6464 битапримерно от 15 до 17 значащих цифр

Литерал с десятичной точкой или экспонентой (2.5, 1e6) по умолчанию имеет тип float64, и пакет math принимает и возвращает float64. Используйте его, если только память в большом массиве не критична.

Числа с плавающей точкой двоичные, поэтому большинство десятичных дробей хранится приближённо:

Отсюда два правила. Никогда не сравнивайте float через == после арифметики. И никогда не храните деньги во float: используйте целое число копеек или библиотеку десятичных чисел.

Деление float на ноль даёт +Inf, -Inf или NaN вместо паники. Деление целого на ноль вызывает панику во время выполнения (runtime error: integer divide by zero), а константный нулевой делитель это ошибка компиляции.

Булевы значения

bool хранит true или false, нулевое значение false. Go не считает числа, пустые строки или nil булевыми значениями. if count {} это ошибка компиляции; пишите if count > 0 {}. Операторы: &&, || и !, причём && и || вычисляются по короткой схеме.

Строки

string это неизменяемая последовательность байтов, обычно текст в UTF-8. len(s) считает байты, а не символы:

é занимает в UTF-8 два байта, поэтому len сообщает 6 для пяти символов. Строки в двойных кавычках обрабатывают escape-последовательности вроде \n; сырые строки в обратных кавычках их не обрабатывают и могут занимать несколько строк. Пакет strings разобран на странице о строках, а UTF-8 подробно описан на странице о рунах и байтах.

byte и rune

ПсевдонимТо же, чтоХранит
byteuint8один байт сырых данных
runeint32одну кодовую точку Unicode

Это псевдонимы, а не новые типы: byte и uint8 взаимозаменяемы без преобразования. Имена лишь говорят, что означает число.

Комплексные числа

В Go есть встроенные комплексные типы complex64 и complex128, функции real, imag и пакет math/cmplx:

Они нужны немногим программам, но в обработке сигналов и некоторых численных задачах без них не обойтись.

Составные и ссылочные типы

Базовые типы складываются в составные. У каждого есть своя страница:

ТипПримерНулевое значение
массив[3]intтри нуля
слайс[]intnil
мапаmap[string]intnil
структураstruct{ X, Y int }все поля обнулены
указатель*intnil
функцияfunc(int) intnil
каналchan intnil
интерфейсerror, anynil

any это псевдоним interface{} (с Go 1.18), он может хранить значение любого типа.

Именованные типы

Можно определить новый тип на основе существующего. Представление у него то же, но это отдельный тип, и у него могут быть методы:

type Celsius float64
type UserID int64

var t Celsius = 21.5
var f float64 = t // compile error: cannot use t (variable of float64 type Celsius) as float64 value in variable declaration

В этой строгости и смысл: UserID нельзя случайно передать туда, где ожидается OrderID. Если преобразование задумано, пишите его явно: float64(t). Правила описаны на странице о преобразовании типов, там же функции strconv для перехода между числами и строками.

Нулевые значения

У каждого типа есть нулевое значение, которое хранит переменная, пока вы ничего не присвоили: 0 для чисел, false для bool, "" для строк и nil для указателей, слайсов, мап, каналов, функций и интерфейсов. Неинициализированных переменных в Go нет.

Часто задаваемые вопросы

Какой размер у int в Go?

int и uint занимают 64 бита на 64-битных платформах (amd64, arm64) и 32 бита на 32-битных. Если нужен фиксированный размер, например для формата файла или сетевого протокола, используйте int32, int64, uint8 и так далее. Для обычных счётчиков, индексов и длин берите int.

Как вывести тип переменной в Go?

Используйте глагол %T: fmt.Printf("%T\n", x) печатает int, float64, []string, main.User и так далее. В коде reflect.TypeOf(x) возвращает ту же информацию в виде значения, которое можно исследовать.

Чем byte отличается от rune в Go?

byte это псевдоним uint8, он хранит один байт сырых данных. rune это псевдоним int32, он хранит одну кодовую точку Unicode. Строка это последовательность байтов; обход через for range декодирует её в руны.

Что использовать в Go: float32 или float64?

float64, если нет причин поступить иначе. Это тип по умолчанию для литералов с плавающей точкой, с ним работает пакет math, и его точность примерно от 15 до 17 значащих десятичных цифр против примерно от 6 до 9 у float32. float32 выбирайте, только чтобы вдвое сократить память в больших массивах или чтобы соответствовать внешнему формату.

Какое максимальное значение int в Go?

Используйте константы пакета math: math.MaxInt (9223372036854775807 на 64-битных платформах), math.MinInt, math.MaxInt64, math.MaxUint32 и так далее. Арифметика, вышедшая за предел, во время выполнения молча переполняется по кругу; паники не будет.

Coddy programming languages illustration

Учитесь программировать с Coddy

НАЧАТЬ