Базові (зумовлені) типи¶
Go постачається з фіксованим невеликим набором вбудованих типів. Жодних інших примітивних типів не існує — все інше будується з цих.
Цілі числа¶
Фіксованого розміру¶
var a int8 = -128 // -128 .. 127
var b int16 = 32_000 // _ дозволяється як роздільник цифр
var c int32 = 2_000_000_000 // до ~2,1×10⁹
var d int64 = 9_000_000_000_000_000_000 // до ~9,2×10¹⁸
var u uint8 = 255 // 0 .. 255
var v uint16 = 65_535
var w uint32 = 4_000_000_000 // до ~4,3×10⁹
var x uint64 = 18_000_000_000_000_000_000 // до ~1,8×10¹⁹
Залежні від архітектури¶
var n int // 32 або 64 біти відповідно до платформи
var u uint // те саме, що int, але без знаку
var p uintptr // достатньо великий для зберігання сирого значення вказівника
int — це не псевдонім int64. Навіть на 64-бітній машині, де вони мають однаковий розмір, це різні типи — дивіться 03-type-conversions.md.
Псевдоніми¶
Існують два псевдоніми цілих чисел:
Використовуйте byte при роботі з бінарними даними ([]byte) і rune — при роботі з символами рядка.
Числа з рухомою комою¶
Обидва відповідають стандарту IEEE 754. float64 є типом за замовчуванням для нетипізованих констант з рухомою комою і використовується в 99% випадків. Не вживайте float32 без зваженої причини (розкладка в пам'яті, GPU-буфери тощо).
У стандартній бібліотеці немає десяткових типів — якщо потрібна точна десяткова арифметика (наприклад, для грошей), зверніться до github.com/shopspring/decimal або подібного пакету.
Комплексні числа¶
Потрібні рідко — більшість коду може ігнорувати complex64 / complex128.
Булевий тип¶
bool не перетворюється на int. Не можна писати if 1 { ... } або if someInt { ... } — це помилка компіляції. Умова в if/for обов'язково повинна бути bool.
var n int = 1
if n { // compile error: non-bool n (type int) used as if condition
fmt.Println("nope")
}
if n != 0 { // ok
fmt.Println("yep")
}
З досвіду Python: немає істинності/хибності. Порожні рядки, порожні зрізи, нуль і
nilне є неявно хибними. Завжди пишіть явне порівняння.
Рядок¶
var greeting string = "hello, 世界"
fmt.Println(len(greeting)) // 13 — кількість БАЙТІВ, а не символів!
fmt.Println(greeting[0]) // 104 — байт 'h'
("hello, " — це 7 ASCII-байтів; 世 та 界 — по 3 UTF-8 байти кожен.)
Два неочевидні факти:
- Рядки незмінні. Не можна робити
s[0] = 'H'— помилка компіляції. len(s)— це байти, а не символи. Оскільки рядки Go кодуються в UTF-8, один символ на кшталт世може займати 3 байти. Щоб підрахувати символи (руни):
import "unicode/utf8"
s := "世界"
fmt.Println(len(s)) // 6 (байти)
fmt.Println(utf8.RuneCountInString(s)) // 2 (руни)
Для перебору по рунах використовуйте range:
for i, r := range "hi世" {
fmt.Printf("byte index %d, rune %c (%d)\n", i, r, r)
}
// output:
// byte index 0, rune h (104)
// byte index 1, rune i (105)
// byte index 2, rune 世 (19990)
З досвіду Python: рядки Python 3 — це послідовності кодових точок Unicode;
s[0]для"世"повертає"世". Рядки Go — це байтові послідовності, інтерпретовані як UTF-8;s[0]для"世"повертає перший байт, а не перший символ.
Нетипізовані константи — коротке введення¶
Константи можуть бути нетипізованими аж до моменту використання.
const small = 10 // нетипізована цілочисельна константа
var a int = small // ok — small стає int
var b int64 = small // ok — small стає int64
var c float64 = small // ok — small стає float64
Якби ви написали const small int = 10, скомпілювався б лише перший рядок. Саме нетипізовані константи дозволяють писати x := 1.5 і отримувати float64 без зайвих дій.
Типи за замовчуванням, якщо контекст вимагає конкретного типу:
| Форма константи | Тип за замовчуванням |
|---|---|
ціле число (42, 0x2a) |
int |
число з рухомою комою (3.14, 1e10) |
float64 |
руна ('A') |
rune (тобто int32) |
рядок ("hi") |
string |
булеве (true) |
bool |
комплексне (2i) |
complex128 |
Що не є вбудованим типом¶
Речі, які Python-розробник може очікувати, але яких не існує:
- Немає ключових слів
list/dict/set— єslice,map, вбудованого множини немає (використовуйтеmap[T]struct{}). - Немає
tuple— використовуйте множинне повернення або структуру. - Немає
decimal—float64або сторонній модуль. - Немає ключового слова
bigint— використовуйтеmath/big.Int. - Немає
None— використовуйтеnil(дійсний лише для вказівника, зрізу, мапи, каналу, функції, інтерфейсу).