Нулевые значения
Что лежит в новой коробке, в которую ещё ничего не положили? В Go ответ всегда известен заранее. Каждая новая коробка приходит с содержимым по умолчанию, и оно зависит от её формы: в коробке для чисел лежит 0, в коробке для текста — пустая строка.
Переменную можно объявить через var без начального значения. В некоторых языках чтение такой переменной — ошибка или случайное число из памяти. В Go её значение всегда определено:
package main
import "fmt"
func main() {
var n int
var f float64
var s string
var ok bool
fmt.Println(n, f, s, ok) // 0 0 false
}Каждая переменная, объявленная без значения, получает нулевое значение своего типа. Поэтому в Go нет ошибки «переменная не инициализирована»: читать переменную можно сразу после объявления.
Давайте разберём вывод 0 0 false по частям:
- Первый
0— значениеn. - Второй
0— значениеf: нулевое значениеfloat64выводится без точки. - Два пробела подряд — это пустая строка
s:fmt.Printlnпоставил пробел до неё и после неё. false— нулевое значениеok.
Значения по типам
| Тип | Нулевое значение |
|---|---|
int, float64 | 0 |
string | "", пустая строка |
bool | false |
У некоторых типов Go нулевое значение называется nil и означает «ничего». К string это не относится: строка никогда не бывает nil, а пустая строка записывается как "".
Здесь картинка с коробкой неточна. Пустая коробка в жизни — это «ничего». А новая переменная в Go не пуста: в ней лежит настоящее значение, например 0, и с ним можно считать, сравнивать и печатать.
Где появляется нулевое значение
Нулевое значение получает переменная, объявленная через var без значения:
- короткое объявление без значения не бывает: справа от
:=всегда стоит значение; - поэтому переменную с нулевым значением объявляют только через
var; - переменная, объявленная через
varбез значения вне функций, надfunc main, тоже получает нулевое значение.
Нулевое значение как начало
Нулевое значение удобно как начальное. Счётчик или сумму объявляют через var и сразу начинают прибавлять. Запись var total int = 0 говорит то же самое, только длиннее:
var total int
total = total + 5
total = total + 7
fmt.Println(total) // 12Давайте пройдём пример по строкам:
var total int—totalначинает с0.total = total + 5— теперь вtotalлежит5.total = total + 7— теперь12.fmt.Println(total)печатает12.
Вывод через Printf
Пустую строку в выводе Println не видно. fmt.Printf с подходящими знаками формата показывает каждое значение явно:
var n int
var s string
var ok bool
fmt.Printf("%q %d %t\n", s, n, ok) // "" 0 falseКаждый знак формата печатает значения своего типа:
%q— строку в двойных кавычках, поэтому пустая строка видна как"", а строка из одного пробела — как" ";%d— целое число;%t—trueилиfalse.
Если знак не подходит к типу аргумента, программа не останавливается. Для строки fmt.Printf("%d\n", s) печатает %!d(string=).
Нулевые значения — частый вопрос на собеседовании. Обычно показывают такую программу и спрашивают, что она напечатает. Ответ требует знать две вещи:
- нулевое значение каждого типа;
- как его выводит каждый знак формата.
Частая ошибка
Пустую строку сравнили с nil. Оператор == сравнивает два значения и даёт true или false:
var s string
fmt.Println(s == nil) // ✗invalid operation: s == nil (mismatched types string and untyped nil)Значение типа string не может быть nil, и компилятор отвергает такое сравнение. Чтобы проверить, пуста ли строка, сравните её с "": s == "".
Главное
- Переменная, объявленная через
varбез значения, получает нулевое значение своего типа и сразу готова к чтению. - Нулевое значение чисел —
0, строки —"",bool—false; строка никогда не бываетnil. %dпечатает целое,%q— строку в кавычках,%t—trueилиfalse, поэтому пустая строка видна как"".
Подпишись, чтобы пройти курс
Курс бесплатный. Войди через Telegram и подпишись на канал — откроются все уроки.