Памятка блока 1
Справочник по дням 01–04. Читать подряд не нужно. Обязательное на этой странице — только блок «Попробуйте сейчас» ниже. Остальное открывайте, когда понадобится: на контрольной точке, в следующих блоках, когда встретится незнакомое сообщение компилятора. Все выводы и сообщения в таблицах — настоящие, Go 1.27.
Попробуйте сейчас: словарик до десяти разборов.
Цель: в
~/errors.mdне меньше десяти строк «текст ошибки — что это значило в вашем коде».Доведите словарик
~/errors.mdдо десяти разборов. Сообщения, которых у вас в нём ещё нет, получите сами: скопируйте программу разминки в черновик и ломайте её способами из таблицы «Ошибки компилятора» ниже — по одному за раз. Копия заменит то, что лежит в черновике.▶ Выполнитеcp ~/gocourse/day05/warmup/main.go ~/gocourse/day05/scratch/main.go cd ~/gocourse/day05/scratch go run .Каждое новое сообщение — строкой в
~/errors.md: текст ошибки, тире, что это значило в вашем коде. Двоеточие вместо тире не засчитывается: оно есть в каждом сообщении компилятора. Переписанная из таблицы колонка «что значит» памяти не оставляет.Готово, когда: в
~/errors.mdне меньше десяти строк, в каждой — текст ошибки, тире и разбор (пункт проверкиerrors).
Команды
| Команда | Что делает | День |
|---|---|---|
pwd, ls, ls -l |
где я; что в папке; подробно | 01 |
cd папка, cd .., cd |
перейти; на уровень вверх; домой | 01 |
mkdir папка, cat файл |
создать папку; напечатать файл | 01 |
code . |
открыть текущую папку в VS Code | 01 |
go run . |
собрать программу из текущей папки и сразу запустить | 01 |
go build, ./имя |
собрать исполняемый файл; запустить его | 01 |
gofmt -l ., gofmt -w main.go |
какие файлы не отформатированы; отформатировать | 01 |
go vet . |
найти подозрительное, что пропускает компилятор | 03 |
go doc strings.Repeat |
справка по функции пакета | 04 |
Скелет программы
package main
import (
"fmt"
"strings"
)
func main() {
// данные
// расчёт
// печать
}Один пакет — import "fmt", несколько — в скобках, по строке на пакет. Подключённый и неиспользованный пакет — ошибка компиляции.
Переменные и присваивание — день 02
| Запись | Что делает |
|---|---|
qty := 5 |
объявить переменную и присвоить значение; тип — по значению |
var qty int |
объявить с нулевым значением: 0 у int, "" у string, 0 у float64, false у bool |
qty = qty + 1 |
новое значение из старого; справа — значение до присваивания |
qty += 3, qty -= 3 |
то же короче |
qty++, qty-- |
плюс один, минус один |
a, b = b, a |
обмен: обе правые части считаются до присваивания |
const vat = 20 |
константа — менять нельзя |
total := price * qty |
копия результата на момент выполнения, не формула |
Имена: буквы, цифры, _, не с цифры; регистр важен. Внутри функции объявляют :=, снаружи — только var и const.
Типы и арифметика — день 03
| Выражение | Результат | Почему |
|---|---|---|
7 / 2 |
3 |
деление целых отбрасывает дробь |
7 % 2 |
1 |
остаток от деления |
7.0 / 2, float64(7) / 2 |
3.5 |
хотя бы одно дробное — деление дробное |
int(f) при f := 3.99 |
3 |
дробь отбрасывается, не округляется |
1205 / 100, 1205 % 100 |
12, 5 |
рубли и копейки из копеек |
2 + 3*4, (2+3)*4 |
14, 20 |
порядок действий как в математике |
50/12*12, 50*12/12 |
48, 50 |
где стоит деление, там и теряется дробь |
float64(1) / 3 |
0.3333333333333333 |
дробные числа хранятся приближённо |
"шт" + "." |
шт. |
склейка строк; строку с числом + не склеивает |
Деньги — в копейках, в int. Считать целыми, печатать через fmt.Printf("%d.%02d руб.\n", sum/100, sum%100). Дробь вида 0,1 в двоичной памяти точно не записывается, и копейки начинают «плыть».
Printf — день 03
Одна строка со всеми глаголами:
fmt.Printf("%d|%s|%v|%T|%.2f|%02d|%%\n", 42, "шт", true, 3.5, 2.456, 5)42|шт|true|float64|2.46|05|%| Глагол | Что печатает |
|---|---|
%d |
целое |
%s |
строку |
%v |
любое значение в обычном виде |
%T |
тип значения |
%.2f |
дробное с двумя знаками после точки, с округлением |
%02d |
целое не короче двух цифр, с ведущим нулём |
%% |
сам знак процента |
\n |
перевод строки — Printf сам его не ставит |
Готовые функции — день 04
| Вызов | Результат |
|---|---|
strings.ToUpper("кабель usb") |
КАБЕЛЬ USB |
strings.ToLower("SK-4471") |
sk-4471 |
strings.TrimSpace(" sk 4471 ") |
sk 4471 — пробелы по краям убраны |
strings.ReplaceAll("sk 4471 b", " ", "-") |
sk-4471-b |
strings.Repeat("=", 5) |
===== |
strings.Contains("стретч-плёнка", "плёнка") |
true |
strings.HasPrefix("SK-4471", "SK") |
true |
strings.Count("a-b-c", "-") |
2 |
len("кабель") |
12 — байтов: кириллическая буква занимает два |
utf8.RuneCountInString("кабель") |
6 — символов; пакет unicode/utf8 |
strconv.Itoa(42) + " шт." |
42 шт. |
fmt.Sprintf("%d.%02d", 1205/100, 1205%100) |
12.05 — строка, а не печать; из дополнительных материалов дня 04 (course extra 04) |
math.Round(2.5), math.Floor(2.7), math.Ceil(2.1) |
3, 2, 3 — все три возвращают float64 |
min(3, 7), max(3, 7) |
3, 7; из дополнительных материалов дня 04 (course extra 04) |
Функция возвращает результат — его надо записать в переменную или сразу передать дальше. Сама по себе она ничего не меняет.
Ошибки компилятора
Слева — текст после ./main.go:строка:колонка:.
| Сообщение | Что значит | Как выглядит в коде | Что делать |
|---|---|---|---|
undefined: fmt.println (but have Println) |
не тот регистр | fmt.println(...) |
fmt.Println |
newline in string |
строка не закрыта кавычкой | fmt.Println("Склад) |
закрыть кавычку |
syntax error: unexpected EOF, expected } |
не закрыта фигурная скобка | нет последней } |
закрыть |
syntax error: unexpected semicolon or newline before { |
{ перенесена на новую строку |
func main() и { ниже |
{ на строке с func main() |
syntax error: unexpected literal 7 in argument list; possibly missing comma or ) |
нет запятой между аргументами | fmt.Println("Товаров:" 7) |
поставить запятую |
"strings" imported and not used |
пакет подключён, но не нужен | "strings" в import без вызовов |
убрать из import |
undefined: strings |
пакет используется, но не подключён | strings.ToUpper(...) без импорта |
добавить в import |
declared and not used: reserved |
переменная объявлена и не используется | reserved := 15, дальше ни разу |
использовать или удалить |
no new variables on left side of := |
:= для уже объявленной переменной |
total := total + 450 |
= вместо := |
undefined: totl |
такого имени нет — опечатка или не объявлено | fmt.Println(totl) |
исправить имя |
syntax error: non-declaration statement outside function body |
:= вне функции |
limit := 100 над func main |
внутрь main или var limit = 100 |
cannot assign to vat (neither addressable nor a map index expression) |
присваивание константе | const vat = 20, потом vat = 22 |
переменная вместо константы |
cannot use "пять" (untyped string constant) as int value in assignment |
в переменную int кладут строку |
qty := 5, потом qty = "пять" |
значение того же типа |
invalid operation: price * rate (mismatched types int and float64) |
действие над разными типами | 4590 * 1.2 через переменные |
float64(price) * rate |
invalid operation: "Остаток: " + total (mismatched types untyped string and int) |
строку склеивают с числом | "Остаток: " + total |
Println("Остаток:", total) или strconv.Itoa(total) |
cannot use 2.5 (untyped float constant) as int value in variable declaration (truncated) |
дробь в целую переменную | var qty int = 2.5 |
целое значение или float64 |
1.2 (untyped float constant) truncated to int |
целое умножают на дробную константу | total = total * 1.2 при total := 450 |
считать в float64 или целыми: total * 12 / 10 |
cannot convert 3.99 (untyped float constant) to type int |
int() от дробной константы |
int(3.99) |
от дробной переменной: int(f) при f := 3.99 даёт 3; константа без дроби, int(4.0), собирается |
invalid operation: operator % not defined on kg (variable of type float64) |
остаток бывает только у целых | kg % 2 при kg := 7.5 |
считать в целых: граммы, копейки |
invalid operation: division by zero |
деление на ноль прямо в коде | 10 / 0 |
исправить делитель |
not enough arguments in call to strings.Repeat |
аргументов меньше, чем нужно; ниже have — что передали, want — что ждёт функция |
strings.Repeat("=") |
strings.Repeat("=", 5) |
too many arguments in call to strconv.Itoa |
аргументов больше, чем нужно | strconv.Itoa(5, 10) |
strconv.Itoa(5) |
cannot use "3" (untyped string constant) as int value in argument to strings.Repeat |
аргумент не того типа | strings.Repeat("=", "3") |
strings.Repeat("=", 3) |
cannot use price (variable of type float64) as int value in argument to strconv.Itoa |
Itoa принимает только int |
strconv.Itoa(price) при price := 12.5 |
int(price) или fmt.Sprintf("%.2f", price) из course extra 04 |
cannot use math.Ceil(x) (value of type float64) as int value in variable declaration |
функции math возвращают float64 |
var boxes int = math.Ceil(x) |
int(math.Ceil(x)) |
len(name) (value of type int) is not used |
результат вызова выброшен | строка len(name) сама по себе |
записать в переменную |
Собирается, но не то
Компилятор молчит — ошибка видна только при запуске или через go vet.
Деление на ноль при запуске. Делитель — переменная, и ноль в ней компилятор не видит:
stagiaire@lab:~/gocourse/day05/scratch$ go run .
panic: runtime error: integer divide by zero
goroutine 1 [running]:
main.main()
/home/stagiaire/gocourse/day05/scratch/main.go:8 +0x9
exit status 2Читать первую строку и main.go:8 — номер строки с делением.
| Что видите | Что это значит | Что делать |
|---|---|---|
Цена: %!d(float64=12.5) руб.; go vet: fmt.Printf format %d has arg price of wrong type float64 |
глагол не подходит к типу | %.2f для дробных, %d для целых |
%!d(MISSING) шт.; go vet: fmt.Printf format %d reads arg #1, but call has 0 args |
в Printf глагол есть, значения нет |
передать значение после строки формата |
строка не стала заглавной, компилятор и go vet молчат |
strings.ToUpper(name) без присваивания |
name = strings.ToUpper(name) |
12 вместо 6 символов |
len считает байты |
utf8.RuneCountInString |
процент или доля — 0 |
целые поделены раньше, чем умножены: дробь отбросилась сразу, и до умножения дошёл ноль | умножать до деления, а не после |
| переменная «не обновилась» | присваивание скопировало старое значение | пересчитать после изменения |
| два числа в выводе поменялись местами | аргументы Printf не в том порядке, что глаголы |
сверить глаголы и аргументы по порядку |
Дальше: правила контрольной точки — course next