Собрать и починить
Два последних приёма дня тренируют чтение с разных сторон. В задаче Парсонса код написан, но перемешан: нужно понять, в каком порядке он может работать. В починке порядок верный, но одна строка делает не то.
Задача Парсонса
Ситуация. Программа разрезана на строки, они перемешаны, и к ним подмешаны одна-две лишние — похожие на настоящие, но ошибочные. Писать новый код не нужно. Такие задачи тренируют то, что нужно для чтения чужого кода: видеть устройство программы и зависимости между строками.
Как собирать
- Скелет:
package main, потомimport ( ... )с пакетами внутри, потомfunc main() {и в конце}. Эти строки ставятся первыми. - Порядок вывода: строки с
Println— в том порядке, в каком идут строки нужного вывода. - Зависимости: переменная объявляется выше строки, где используется.
- Лишние строки. Ищите пары похожих: в одной из пары что-то не сходится с сигнатурой функции или с типами. Сигнатуру покажет
go doc. - Сохранить и запустить.
Ctrl+Sрасставит отступы и отсортирует импорты, но пакетов не добавит и не удалит.
Попробуйте сейчас: собрать пример в черновике.
Цель: из перемешанных строк собрать программу и увидеть, почему лишняя строка лишняя.
- Наберите перемешанные строки в черновик — как есть, в этом порядке:
✎ Наберите в файлscratch/main.gofmt.Println(strings.Repeat("-", width)) func main() { width := 12 fmt.Println(strings.Repeat(width, "-")) package main } fmt.Println("Склад открыт") import ( "strings" "fmt" )
- Запустите как есть и прочитайте сообщение — так выглядит не собранный файл:
▶ Выполнитеcd ~/gocourse/day04/scratch go run .
- Переставьте строки по правилам выше и удалите лишнюю. Нужный вывод:
Вывод · это печатает программа, набирать не нужноСклад открыт ------------
- Теперь поставьте лишнюю строку вместо правильной:
strings.Repeat(width, "-"). Компилятор выдаст два сообщенияcannot use ...— на каждый аргумент. Верните правильную строку.Готово, когда: после сборки
go run .печатаетСклад открыти черту, а с лишней строкой вы видели дваcannot use ....
Как это выглядит собранным
package main
import (
"fmt"
"strings"
)
func main() {
width := 12
fmt.Println("Склад открыт")
fmt.Println(strings.Repeat("-", width))
}Лишней была строка fmt.Println(strings.Repeat(width, "-")): в сигнатуре func Repeat(s string, count int) string первым стоит строка.
Ошибки, которые встретятся при сборке
| Что видите | Что это значит | Что делать |
|---|---|---|
expected 'package', found fmt с номером первой строки кода (в черновике main.go:1:2, в parsons main.go:4:2) |
первая строка кода — не package main: так выглядит не собранный файл |
package main — первой строкой |
main.go:1:1: expected 'package', found 'import' |
import выше package main |
поменять местами |
./main.go:8:2: syntax error: non-declaration statement outside function body |
строка с действием вне func main() { ... } |
перенести внутрь скобок |
./main.go:9:14: undefined: title и ./main.go:10:2: declared and not used: title |
переменная используется выше объявления | поменять строки местами |
./main.go:10:7: no new variables on left side of := |
две строки объявляют одну переменную — одна лишняя | удалить лишнюю из пары |
"strconv" imported and not used вместе с invalid operation: ... (mismatched types untyped string and int) |
взята строка, где число склеивают со строкой напрямую | взять вариант со strconv.Itoa |
Починка, которая собирается
В день 01 сломанные программы не собирались, и компилятор показывал место ошибки. Опаснее другие: программа собирается и молча печатает не то. Порядок такой: найти первую строку, которая отличается от нужной; понять, откуда в ней значение и где ему полагалось измениться; трассировать main до этой строки; одна правка — и снова запуск.
Частая причина на сегодня — выброшенный результат с первой страницы: функция вызвана, а ответ никуда не положен.
Словарик
К концу дня в ~/errors.md должно быть минимум девять разборов; записи прошлых дней считаются, сообщения берите из таблиц «Что может пойти не так».
Формат прежний: слева — текст ошибки, как его напечатал Go, тире, справа — что это значило у вас. Двоеточие вместо тире не засчитывается: оно есть в каждом сообщении компилятора.
not enough arguments in call to strings.Repeat — забыл, сколько раз повторять; have — что передал, want — что нужноПопробуйте сейчас: задача Парсонса parsons.
Цель:
parsons/main.goсобран из строк заготовки и печатает четыре строки изTASK.txt.▶ Выполнитеcd ~/gocourse/day04/parsons cat TASK.txtОткройте
main.goв VS Code и переставляйте строки, не меняя их: строку двигаетAlt+↑иAlt+↓. Две лишние удалите, сохраните и запустите:▶ Выполнитеgo run .Пока строки не на своих местах,
Ctrl+Sотступы не расставит: форматируется только код без синтаксических ошибок. Испортили файл — оригинал в~/.course/orig/day04/parsons/main.go.Готово, когда:
go run .печатает ровно четыре строки изTASK.txt, а в файле только строки заготовки без двух лишних (пункт проверкиparsons).
Попробуйте сейчас: вторая починка fix2.
Цель:
fix2печатает то, что обещано в комментарии, после точечной правки, а в словарике — девять разборов.▶ Выполнитеcd ~/gocourse/day04/fix2 go run .Сравните вывод с комментарием в начале файла: какая строка отличается, откуда в ней значение и где оно должно было измениться? Здесь хватает одной строки, проверка принимает не больше двух и вторым запуском — с другими
skuиcell— ловит вписанный ответ.Потом доведите словарик
~/errors.mdдо девяти строк.Готово, когда:
go run .печатает обе строки из комментария, изменено не больше двух строк (пунктfix2), а в~/errors.mdне меньше девяти строк «текст ошибки — что значило» (пунктerrors).
Материал дня закончен. Задания — course lab 04, дополнительное чтение — course extra 04