День 01 · Программа, терминал, первый запуск · страница 6 из 6

Ошибки компилятора

Программа не собралась, и терминал выдал строки на английском. У опытных разработчиков такие сообщения появляются каждый день; разница в том, что они читают их за секунды. Этому и научимся.


Из чего состоит сообщение

Ситуация. Вы запустили программу и получили:

Пример · только посмотреть, набирать не нужно
stagiaire@lab:~/gocourse/day01/fix1$ go run .
# day01/fix1
./main.go:9:6: undefined: fmt.println (but have Println)

Как читать. Первая строка # day01/fix1 — какой пакет собирался. Вторая — сама ошибка, у неё строгий формат:

Код для чтения · разбираем, набирать не нужно
./main.go:9:6: undefined: fmt.println (but have Println)
    ↑     ↑ ↑       ↑
  файл строка │   что не так
           колонка
Кусок Что значит
./main.go в каком файле
9 номер строки
6 номер колонки — где в строке начинается проблема
undefined: fmt.println текст ошибки: имя fmt.println не определено
(but have Println) подсказка компилятора: зато есть Println

Колонка считается в байтах, а не в буквах. Латинская буква, цифра, знак и табуляция — один байт, русская буква — два. Поэтому в строке с русским текстом номер колонки больше, чем число видимых символов:

Вывод · это печатает программа, набирать не нужно
./main.go:9:49: newline in string

В строке fmt.Println("Заказов сегодня: 12) всего 33 символа, а колонка — 49. Считать до 49 не нужно: ориентируйтесь на номер строки и на то место, которое подчёркнуто в редакторе.

Номер строки виден в VS Code слева от кода. Там же ошибка подчёркнута красным, а если навести мышь — появится тот же текст. Все ошибки проекта списком — вкладка Problems, Ctrl+Shift+M. Текст одинаковый: и редактор, и терминал спрашивают один и тот же компилятор.


Порядок работы с ошибкой

  1. Прочитать сообщение целиком, до конца строки. Подсказка часто в самом конце — как (but have Println).
  2. Перейти на строку. Смотреть в указанное место, а не на весь файл.
  3. Сравнить с образцом. Как эта конструкция выглядела в работающей программе на третьей странице?
  4. Исправить одно и запустить снова.

Если сообщений несколько, начинайте с первого. Одна настоящая ошибка часто даёт несколько строк:

Вывод · это печатает программа, набирать не нужно
./main.go:9:49: newline in string
./main.go:9:49: syntax error: unexpected newline in argument list; possibly missing comma or )

Строка не закрыта кавычкой, и компилятор запутался дальше. Закройте кавычку — исчезнут обе строки.


Что может пойти не так: ошибки этой недели

Все тексты ниже — настоящий вывод Go 1.27.

Что видите Что это значит Как выглядит в коде Что делать
main.go:1:1: expected 'package', found 'EOF' файл на диске пустой: код набран в редакторе, но не сохранён на вкладке файла белая точка Ctrl+S — на вкладке появится крестик
undefined: fmt.println (but have Println) имя написано не тем регистром fmt.println(...) fmt.Println
undefined: fmt.Printn опечатка в имени функции fmt.Printn(...) fmt.Println
undefined: fmt пакет используется, но не подключён нет import "fmt" добавить import "fmt" после package main
"os" imported and not used пакет подключён, но не используется — в Go это ошибка import "os" без вызовов os. удалить лишний импорт
newline in string строка не закрыта кавычкой до конца строки кода fmt.Println("Привет) закрыть кавычку
syntax error: unexpected EOF, expected } файл кончился, а фигурная скобка не закрыта нет последней } закрыть скобку. EOF — end of file, конец файла
syntax error: unexpected semicolon or newline before { открывающая скобка перенесена на новую строку func main() и { на следующей строке { на той же строке, что и func main()
invalid character U+201C '“' in identifier и вторая строка про U+201D '”' «умные» кавычки “ ” вместо обычных " — так бывает при копировании из документов fmt.Println(“Привет”) заменить на прямые кавычки "
more than one character in rune literal строка в одинарных кавычках fmt.Println('Привет') двойные кавычки
syntax error: unexpected literal 7 in argument list; possibly missing comma or ) нет запятой между аргументами fmt.Println("Товаров:" 7) поставить запятую

Почему скобку нельзя переносить: Go сам расставляет невидимые точки с запятой в концах строк. После func main() на отдельной строке он поставил бы её — и { на следующей строке оказалась бы оторвана от функции. Отсюда unexpected semicolon or newline before {.


Словарик ошибок

Встретили новое сообщение — запишите его. Файл ~/errors.md в домашней папке будет с вами весь курс; через месяц в нём соберётся ваш личный справочник, и большинство ошибок вы будете узнавать по первым словам.

Формат строки — текст ошибки, тире, что это значило:

Образец · набирать не нужно
undefined: fmt.println (but have Println) — написал println с маленькой буквы, функции пакета с большой
"os" imported and not used — подключил пакет, которым не пользуюсь; в Go это ошибка, а не предупреждение
newline in string — забыл закрывающую кавычку в Println

Открыть файл в редакторе:

Пример · только посмотреть, набирать не нужно
stagiaire@lab:~$ code ~/errors.md

Если файла нет, VS Code создаст его при первом сохранении. Проверка дня засчитывает строки не короче 20 символов, в которых между текстом ошибки и разбором стоит тире с пробелами вокруг: « — » (или « - »). Слева от тире — сообщение компилятора, латиницей, как он его напечатал; справа — разбор по-русски. Поэтому не засчитываются ни скопированная строка компилятора без разбора, ни произвольный текст с тире посередине. Файл — именно ~/errors.md в домашней папке, а не в папке дня.


Попробуйте сейчас: что выведет компилятор?

Цель: по сообщению компилятора назвать строку с ошибкой и сдать ответ.

Программа:

Код для чтения · разбираем, набирать не нужно
package main

import "fmt"

func main() {
	fmt.Println("Север")
	fmt.Println(y)
}

Компилятор ответил:

Вывод · это печатает программа, набирать не нужно
./main.go:7:14: undefined: y

На какой строке ошибка? Ответьте числом:

▶ Выполните · выделенное замените своим
course answer day01.q3 ЧИСЛО

Вместо ЧИСЛО — номер строки, на которой ошибка.

Готово, когда: course answer ответил Принято: day01.q3 = … (пункт проверки q3).


Попробуйте сейчас: почините fix1, fix2, fix3.

Цель: три программы, которые не собирались, печатают обещанное в своих комментариях, а новые сообщения записаны в словарик.

В папках fix1, fix2, fix3 лежат три программы, которые не собираются. В первых строках каждой — комментарий: что она должна напечатать. В каждой программе одна причина ошибки.

1. Запустите fix1:

▶ Выполните
cd ~/gocourse/day01/fix1
go run .

2. Прочитайте сообщение по порядку работы выше: файл, строка, текст. Исправьте в main.go одно место, сохраните, запустите снова. Когда программа напечатает то, что обещано в комментарии, переходите к fix2, потом к fix3.

В fix3 компилятор выдаст три строки: одну про пакет os и две про fmt. Прочитайте все, прежде чем править: одна правка исправит все три.

Правьте точечно — одну-две строки. Проверка сравнит ваш файл с оригиналом из ~/.course/orig/day01 и, если программа переписана заново, пункт задания не зачтёт — даже если вывод верный. Строки import в этот счёт не входят: добавить или заменить пакет можно.

3. Каждое новое сообщение — строкой в ~/errors.md. К концу дня в словарике должно быть минимум три разбора.

▶ Выполните
code ~/errors.md

Готово, когда: go run . в fix1, fix2 и fix3 печатает обещанное в комментарии, в каждом файле изменены одна-две строки, а в ~/errors.md не меньше трёх разборов через тире (пункты проверки fix1, fix2, fix3, errors).


Материал дня закончен. Задания — course lab 01, дополнительное чтение — course extra 01