Первая программа
Напишем программу, которая печатает строчку текста, и разберём её по словам. Каждое слово в ней будет в каждой программе курса.
Где живёт программа
Программа на Go живёт в модуле — папке, в которой лежит файл go.mod. Модуль — граница проекта: команды go ищут go.mod в текущей папке и выше, и всё, что внутри, считают частью одного проекта.
Модуль дня уже создан — это ~/gocourse/day01. Загляните в его go.mod:
stagiaire@lab:~$ cd ~/gocourse/day01
stagiaire@lab:~/gocourse/day01$ cat go.mod
module day01
go 1.27Как читать. module day01 — имя модуля. go 1.27 — на какую версию языка он рассчитан. Больше в нём сегодня ничего нет, и трогать его не нужно. cat — команда, которая печатает содержимое файла.
Внутри модуля каждое задание — своя папка: hello, receipt, fix1. В каждой папке — своя программа.
Открыть модуль в редакторе
Писать код удобнее в VS Code, который вы настроили в день 0. Откройте в нём папку модуля — не отдельный файл:
stagiaire@lab:~/gocourse/day01$ code .Точка означает «текущая папка». Редактор откроется, слева в панели Explorer будут видны папки заданий. Если VS Code спросит, доверяете ли вы авторам файлов, — ответьте Yes, I trust the authors, иначе расширение Go отключится.
Почему именно папка модуля: редактор понимает Go-код только вместе с go.mod. Открытый сам по себе файл он не свяжет с модулем, и половина подсказок пропадёт.
Пишем
Попробуйте сейчас: создайте hello/main.go.
Цель: в папке
helloлежит сохранённый файлmain.goс первой программой.1. В Explorer щёлкните по папке
hello, чтобы она выделилась, затем нажмите значок New File в заголовке панели EXPLORER и назовите файлmain.go. Проверьте, чтоmain.goпоявился подhello, а не рядом сgo.mod.Запасной путь — из терминала:
▶ Выполнитеcd ~/gocourse/day01/hello code main.goРедактор откроет новый файл, на диске он появится при первом сохранении.
2. Напечатайте — именно напечатайте руками:
✎ Наберите в файлhello/main.gopackage main import "fmt" func main() { fmt.Println("Привет, мир!") }3. Сохраните:
Ctrl+S. Пока в файле есть несохранённые изменения, на его вкладке вместо крестика белая точка.Готово, когда:
main.goвиден в Explorer подhello, а на его вкладке крестик, а не белая точка.
Запускаем
Попробуйте сейчас: запустите hello.
Цель: программа из папки
helloнапечатала строкуПривет, мир!.В терминале — в обычном или во встроенном в VS Code (
Ctrl+`) — из папки модуля~/gocourse/day01перейдите в папку программы и запустите:▶ Выполнитеcd hello go run .Что должно получиться:
Вывод · это печатает программа, набирать не нужноПривет, мир!Готово, когда: под
go run .появилась строкаПривет, мир!(пункт проверкиt_gorun).
go run . — «собери программу из этой папки и сразу запусти». Точка — та же «текущая папка». Первый запуск может занять пару секунд: компилятор переводит программу. Строка Привет, мир! — то, что напечатала ваша программа.
Как это читать — по строкам
| Строка | Что значит |
|---|---|
package main |
файл относится к пакету main. Пакет — группа файлов одной папки. Имя main особое: только из такого пакета получается программа, которую можно запустить |
| пустая строка | для глаз; компилятору всё равно |
import "fmt" |
подключить пакет fmt из стандартной библиотеки Go. В нём функции для печати на экран. Название — от format |
func main() { |
объявление функции main. Функция — именованный кусок кода. С функции main программа начинает выполняться. Фигурная скобка { открывает её тело |
fmt.Println("Привет, мир!") |
вызвать функцию Println из пакета fmt и передать ей текст. Println — print line: напечатать и перейти на новую строку |
} |
тело main закончилось — программа завершилась |
Три детали, на которых чаще всего спотыкаются:
- Текст в двойных кавычках — это строка. Кавычки не печатаются, печатается то, что между ними. Кириллица, эмодзи, знаки — всё можно.
- Регистр букв важен.
Printlnиprintln— разные имена. Функции, которые можно вызывать из чужого пакета, в Go всегда начинаются с большой буквы. - Отступ перед
fmt.Println— это табуляция. Сам по себе он для компилятора ничего не значит, но в Go принят единый формат, и редактор расставит отступы сам при сохранении.
Команды выполняются сверху вниз
Добавьте в main вторую строку — тело функции станет таким:
func main() {
fmt.Println("Привет, мир!")
fmt.Println("Я пишу на Go.")
}Здесь показаны только строки функции main: package main и import "fmt" в файле остаются на месте. Файл целиком — в блоке ниже.
stagiaire@lab:~/gocourse/day01/hello$ go run .
Привет, мир!
Я пишу на Go.Программа выполняет строки тела main по порядку, одну за другой. Поменяете строки местами — поменяется порядок вывода. Это правило кажется очевидным, но именно его нарушают, когда читают чужой код «по диагонали».
Формат кода
В Go один принятый формат кода на всех: отступы табуляцией, пробелы вокруг знаков, скобки на своих местах. Расставляет его программа gofmt. В VS Code она срабатывает сама при каждом Ctrl+S. В терминале:
stagiaire@lab:~/gocourse/day01/hello$ gofmt -l .
stagiaire@lab:~/gocourse/day01/hello$ gofmt -w main.gogofmt -l . печатает имена файлов, которые не отформатированы. Пустой вывод — всё в порядке. gofmt -w main.go переформатирует файл на месте. Спорить о расстановке пробелов в Go не принято: как сделал gofmt, так и правильно.
Что может пойти не так
| Что видите | Что это значит | Что делать |
|---|---|---|
go: go.mod file not found in current directory or any parent directory; see 'go help modules' |
вы не внутри модуля — например, в домашней папке | cd ~/gocourse/day01/hello |
no Go files in /home/stagiaire/gocourse/day01 |
вы в папке модуля, а программа лежит в папке hello |
cd hello |
package day01/hello is not a main package |
первая строка файла не package main |
исправить первую строку |
runtime.main_main·f: function main is undeclared in the main package |
нет функции main — чаще всего опечатка в имени: mian, Main |
имя функции ровно main, маленькими буквами |
main.go:1:1: expected 'package', found 'EOF' |
файл на диске пустой: код набран в редакторе, но не сохранён | Ctrl+S — на вкладке белая точка сменится крестиком, потом снова go run . |
| изменили текст, а печатается старый | то же самое: не сохранили | Ctrl+S |
Попробуйте сейчас: доведите hello до двух строк.
Цель:
helloпечатает такой вывод — ровно две строки, с запятой, восклицательным знаком и точкой:Вывод · это печатает программа, набирать не нужноПривет, мир! Я пишу на Go.1. Файл
hello/main.goцеликом:✎ Наберите в файлhello/main.gopackage main import "fmt" func main() { fmt.Println("Привет, мир!") fmt.Println("Я пишу на Go.") }2. Сохраните (
Ctrl+S) и запустите:▶ Выполнитеcd ~/gocourse/day01/hello go run . gofmt -l .
gofmt -l .должен ничего не напечатать. Это первое задание дня — проверка сверит вывод буква в букву.Готово, когда:
go run .печатает эти две строки буква в букву, аgofmt -l .— ничего (пункты проверкиhello_build,hello_out,hello_fmt).
Попробуйте сейчас: что выведет?
Цель: предсказать вторую строку вывода, не запуская программу, и сдать ответ.
1. Не запуская, предскажите, что напечатает программа:
Код для чтения · разбираем, набирать не нужноpackage main import "fmt" func main() { fmt.Println("Раз") fmt.Println("Два", "Три") }Подсказка к синтаксису: в скобках
Printlnможет стоять несколько значений через запятую — он напечатает их в одной строке, разделив пробелом. Подробно об этом — на пятой странице.2. Отправьте, что будет во второй строке вывода:
▶ Выполните · выделенное замените своимcourse answer day01.q1 ВАШ_ОТВЕТВместо
ВАШ_ОТВЕТ— вторая строка вывода, как вы её предсказали.Всё, что после имени вопроса, считается ответом — кавычки ставить не нужно, регистр неважен. Ответ можно отправить заново, засчитывается последний.
3. После ответа проверьте себя запуском. Создайте папку для опытов:
▶ Выполнитеmkdir -p ~/gocourse/day01/scratchТеперь ту же программу нужно набрать — в
scratch/main.go:✎ Наберите в файлscratch/main.gopackage main import "fmt" func main() { fmt.Println("Раз") fmt.Println("Два", "Три") }Запустите:
▶ Выполнитеcd ~/gocourse/day01/scratch go run .Если вывод разошёлся с вашим ответом — перечитайте раздел «Как это читать» выше.
Готово, когда:
course answerответилПринято: day01.q1 = …(пункт проверкиq1).
Дальше: что именно делает go run и чем от него отличается go build — course next