День 04 · Чужой код и готовые функции · страница 7 из 7

Собрать и починить

Два последних приёма дня тренируют чтение с разных сторон. В задаче Парсонса код написан, но перемешан: нужно понять, в каком порядке он может работать. В починке порядок верный, но одна строка делает не то.


Задача Парсонса

Ситуация. Программа разрезана на строки, они перемешаны, и к ним подмешаны одна-две лишние — похожие на настоящие, но ошибочные. Писать новый код не нужно. Такие задачи тренируют то, что нужно для чтения чужого кода: видеть устройство программы и зависимости между строками.

Как собирать

  1. Скелет: package main, потом import ( ... ) с пакетами внутри, потом func main() { и в конце }. Эти строки ставятся первыми.
  2. Порядок вывода: строки с Println — в том порядке, в каком идут строки нужного вывода.
  3. Зависимости: переменная объявляется выше строки, где используется.
  4. Лишние строки. Ищите пары похожих: в одной из пары что-то не сходится с сигнатурой функции или с типами. Сигнатуру покажет go doc.
  5. Сохранить и запустить. Ctrl+S расставит отступы и отсортирует импорты, но пакетов не добавит и не удалит.

Попробуйте сейчас: собрать пример в черновике.

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

  1. Наберите перемешанные строки в черновик — как есть, в этом порядке:
✎ Наберите в файл scratch/main.go
   	fmt.Println(strings.Repeat("-", width))
   func main() {
   	width := 12
   	fmt.Println(strings.Repeat(width, "-"))
   package main
   }
   	fmt.Println("Склад открыт")
   import (
   	"strings"
   	"fmt"
   )
  1. Запустите как есть и прочитайте сообщение — так выглядит не собранный файл:
▶ Выполните
   cd ~/gocourse/day04/scratch
   go run .
  1. Переставьте строки по правилам выше и удалите лишнюю. Нужный вывод:
Вывод · это печатает программа, набирать не нужно
   Склад открыт
   ------------
  1. Теперь поставьте лишнюю строку вместо правильной: 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