День 12 · Несколько результатов и ошибка как результат · страница 7 из 7

Программа целиком, коммиты и словарик

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


Обе темы в одной программе

Ситуация. Накладная: в каждой строке количество. Нужно на каждую строку сказать, сколько выйдет полных коробок и сколько останется россыпью, а на плохой строке — остановиться.

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

import (
	"bufio"
	"errors"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func parseQty(s string) (int, error) {
	text := strings.TrimSpace(s)
	if text == "" {
		return 0, errors.New("пустое количество")
	}
	qty, err := strconv.Atoi(text)
	if err != nil {
		return 0, fmt.Errorf("не число: %v", err)
	}
	return qty, nil
}

func pack(qty int, size int) (int, int) {
	return qty / size, qty % size
}

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	size := 6
	line := 0
	for scanner.Scan() {
		line++
		qty, err := parseQty(scanner.Text())
		if err != nil {
			fmt.Fprintf(os.Stderr, "Ошибка в строке %d: %v\n", line, err)
			os.Exit(1)
		}
		boxes, rest := pack(qty, size)
		fmt.Printf("строка %d: %d шт. - коробок %d, россыпью %d\n", line, qty, boxes, rest)
	}
}

Что увидите.

Пример · только посмотреть, набирать не нужно
stagiaire@lab:~/gocourse/day12/scratch$ printf '17\n5\n' | go run .
строка 1: 17 шт. - коробок 2, россыпью 5
строка 2: 5 шт. - коробок 0, россыпью 5
stagiaire@lab:~/gocourse/day12/scratch$ printf '17\nx\n' | go run .
строка 1: 17 шт. - коробок 2, россыпью 5
Ошибка в строке 2: не число: strconv.Atoi: parsing "x": invalid syntax
exit status 1

Как это читать. В main три строки настоящей работы: взять количество, разложить по коробкам, напечатать. Всё остальное — цикл, номер строки и обработка ошибки. Две функции, у одной два результата, у другой — результат и ошибка; ни одна из них ничего не печатает и не завершает программу.

Ещё раз о порядке в main: сначала вызов, сразу под ним проверка err, и только потом qty идёт в дело. Это тот порядок, в котором вы будете читать чужой Go-код: «вызов — проверка — использование», и если проверки между вызовом и использованием нет, это первое место, куда стоит смотреть при разборе дефекта.


Ритуал перед коммитом

Три команды в папке задания, всегда в одном порядке:

Команда Что проверяет
gofmt -w . отступы и пробелы: правит сама
go vet . подозрительные места, которые компилятор пропускает
go run . < example.txt что программа делает то, что нужно

gofmt и go vet вы знаете с блока 1. Новое — что теперь после них идёт коммит, и в историю попадает уже проверенная работа.


Коммит после каждого задания

Репозиторий и первые коммиты были в дне 11. Сегодня репозиторий вы завели на первой странице, пока ничего не тронуто, — вот так это выглядело:

Пример · только посмотреть, набирать не нужно
stagiaire@lab:~/gocourse/day12$ git status --short
?? go.mod
?? split/
stagiaire@lab:~/gocourse/day12$ git add .
stagiaire@lab:~/gocourse/day12$ git commit -m "день 12: заготовки"
[main (root-commit) b07cfc6] день 12: заготовки
 2 files changed, 6 insertions(+)
 create mode 100644 go.mod
 create mode 100644 split/main.go

Буквы и цифры после [main — номер коммита, у вас он будет другой: он считается из содержимого и времени. Строки ниже — сколько файлов изменилось и сколько строк добавилось.

После второго коммита история читается одной командой:

Пример · только посмотреть, набирать не нужно
stagiaire@lab:~/gocourse/day12$ git log --oneline
944fb03 split: разбор строк заказа
b07cfc6 день 12: заготовки
stagiaire@lab:~/gocourse/day12$ git status --short
stagiaire@lab:~/gocourse/day12$

Пустой ответ git status --short означает, что всё сохранённое в файлах уже записано в историю. Это удобная проверка перед тем, как закрыть день.

Почему коммит стоит последним шагом задания: каждое задание дня заканчивалось своими двумя командами — fix2, split, intake, fix1, trace, — и в истории теперь видно, в каком порядке всё происходило. Один коммит в конце дня этого не показывает: в нём вся работа одной записью. Сообщение пишут о том, что сделано, а не о том, какие файлы тронуты: «split: разбор строк заказа» полезнее, чем «правки».

Собранные программы в историю не кладут: go build -o prog . создаёт файл, который получается из кода за секунду. Для таких файлов есть .gitignore — он был в дне 11:

Пример · только посмотреть, набирать не нужно
stagiaire@lab:~/gocourse/day12$ go build -o prog ./split
stagiaire@lab:~/gocourse/day12$ printf 'prog\n' > .gitignore
stagiaire@lab:~/gocourse/day12$ git status --short
?? .gitignore

Файл prog в списке не появился — git про него больше не спрашивает, а сам .gitignore коммитят: он часть работы. Если вы повторили этот опыт, закоммитьте и его — иначе git status --short так и будет показывать ?? .gitignore:

Пример · только посмотреть, набирать не нужно
stagiaire@lab:~/gocourse/day12$ git add .gitignore
stagiaire@lab:~/gocourse/day12$ git commit -m "не коммитим собранные файлы"
[main dc6cd7a] не коммитим собранные файлы
 1 file changed, 1 insertion(+)
 create mode 100644 .gitignore
stagiaire@lab:~/gocourse/day12$ git status --short
stagiaire@lab:~/gocourse/day12$

Попробуйте сейчас: история дня.

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

1. Посмотрите, что записано и не осталось ли незакоммиченного:

▶ Выполните
cd ~/gocourse/day12
git log --oneline
git status --short

2. Если git status --short что-то печатает — забытое задание или ?? .gitignore после опыта выше, — запишите и это:

▶ Выполните
git add .
git commit -m "что сделали"
git log --oneline

Если git commit отвечает, что не знает, кто вы, выполните две команды настройки из дня 11 — git config --global user.name и user.email — и повторите коммит.

Готово, когда: git log --oneline показывает не меньше трёх строк — по коммиту на задание, — а git status --short после последнего коммита ничего не печатает; пункты git и t_gitlog в course check 12 зелёные.


Что может пойти не так с коммитами

Что видите Что это значит Что делать
fatal: not a git repository (or any of the parent directories): .git команда выполняется не в папке с репозиторием cd ~/gocourse/day12, при необходимости git init
Author identity unknown и просьба выполнить git config подпись автора не настроена две команды git config --global из дня 11
nothing to commit, working tree clean всё уже закоммичено это не ошибка: коммит делают после изменений
в git status --short строка ?? prog в папке лежит собранный файл добавить его имя в .gitignore
коммитов меньше трёх, хотя вы коммитили часть коммитов сделана в другой папке git log --oneline в ~/gocourse/day12 покажет, что попало сюда
git add . добавляет лишние файлы в папке остался мусор от опытов удалить ненужное или перечислить в .gitignore

Репозиторий сегодня местный: он лежит в той же папке, что и работа, и никуда ничего не отправляет. Общий репозиторий, куда складывают работу всей командой, будет в блоке 7 — механика та же, добавится только обмен.


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

К концу дня в ~/errors.md — минимум двадцать четыре разбора: за прошлые дни и за сегодня. Строка засчитывается, если в ней текст ошибки, тире с пробелами вокруг и что это значило. Сегодня встречались:


Попробуйте сейчас: словарик и проверка дня.

Цель: в ~/errors.md двадцать четыре разбора, course check 12 показывает, что осталось.

1. Допишите сегодняшние ошибки в ~/errors.md — каждая строка «текст ошибки — что значило», через тире.

2. Запустите проверку:

▶ Выполните
course check 12

3. Красные пункты доделайте по страницам, указанным рядом. Между запусками проверки — пауза 15 секунд: это время лучше потратить на запуск самой программы.

Готово, когда: пункт errors зелёный и зачтено не меньше 14 пунктов из 17.


Итог дня

Что уносите:

Завтра, в день 13, речь пойдёт не об одной функции, а о целой задаче: какие куски вынести, как их назвать и как разложить готовую программу, ничего не сломав.


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