Типи файлів у дереві Go-коду¶
Вихідні файли, які розпізнає інструмент go¶
| Шаблон імені файлу | Значення |
|---|---|
foo.go |
Звичайний вихідний файл. Компілюється у пакет. |
foo_test.go |
Тестовий файл. Компілюється лише командою go test, ніколи у звичайних збираннях. |
foo_linux.go |
Неявне build-обмеження: компілюється лише коли GOOS=linux. |
foo_amd64.go |
Компілюється лише коли GOARCH=amd64. |
foo_linux_amd64.go |
Компілюється лише коли обидві умови виконуються. |
foo_test_linux.go |
Тестовий файл, обмежений linux. |
_foo.go, .foo.go |
Повністю ігноруються інструментом go. Початковий _ або . — це вимикач. |
doc.go |
Лише конвенція: файл, що містить коментар документації рівня пакету. |
go.mod |
Маніфест модуля. |
go.sum |
База даних контрольних сум модуля / lockfile. |
go.work, go.work.sum |
Файл робочого простору для розробки з кількома модулями. |
Анатомія вихідного файлу .go¶
Кожен Go-вихідний файл дотримується одного скелету:
// Package greet provides a friendly greeting.
package greet // 1. оголошення пакету — обов'язкове, перший рядок без коментарів
import ( // 2. імпорти
"fmt"
"strings"
)
const Exclamation = "!" // 3. оголошення верхнього рівня
// (const, var, type, func — у будь-якому порядку)
// Hello returns a greeting for name.
func Hello(name string) string {
name = strings.TrimSpace(name)
return fmt.Sprintf("Hello, %s%s", name, Exclamation)
}
Два неочевидних правила:
- Регістр контролює видимість. Ідентифікатори, що починаються з великої літери, експортуються з пакету; з малої — є приватними для пакету. Ключових слів
public/privateнемає — компілятор перевіряє це виключно за іменем. - Невикористані імпорти та невикористані локальні змінні є помилками компіляції, а не попередженнями. Це суворо виконується.
Build-обмеження¶
Build-обмеження вирішують, чи включається файл у збирання.
Явні обмеження (//go:build)¶
//go:build linux && (amd64 || arm64)
package cache
// ... код лише для linux на 64-бітних процесорах ...
Правила:
- Рядок
//go:buildповинен з'являтися перед оголошеннямpackage, якому передують лише порожні рядки та інші коментарі. - За ним повинен іти порожній рядок, щоб відрізнити його від коментаря документації пакету.
- Щонайбільше один рядок
//go:buildна файл. - Вираз використовує булеві оператори:
||,&&,!та дужки.
Неявні обмеження з імен файлів¶
Ці обмеження виникають із суфіксів імен файлів — коментар не потрібен.
server_linux.go→ ефективне обмеження//go:build linuxmath_amd64.go→//go:build amd64utils_windows_386.go→//go:build windows && 386
Автоматично задоволені теги¶
Під час будь-якого збирання ці теги є істинними:
- Поточне значення
GOOS(наприклад,linux,darwin,windows). - Поточне значення
GOARCH(наприклад,amd64,arm64). - Тег
unixна будь-якій Unix-подібній ОС. - Використовуваний компілятор:
gcабоgccgo. cgo, якщо cgo увімкнено.- Тег для кожної версії Go аж до поточної:
go1.1,go1.21,go1.22, ... - Будь-які власні теги, передані через
-tagsкомандіgo.
Тестові файли — два різновиди¶
Тестовий файл може оголошувати той самий пакет, який тестує, або окремий пакет _test.
// foo_test.go — внутрішній тест (може бачити неекспортовані ідентифікатори)
package foo
import "testing"
func TestAdd(t *testing.T) {
if got := add(2, 3); got != 5 {
t.Errorf("add(2,3) = %d; want 5", got)
}
}
// foo_test.go — зовнішній тест (тестує лише публічний API)
package foo_test
import (
"testing"
"example.com/foo"
)
func TestPublic(t *testing.T) { /* ... */ }
Пакет може мати обидва різновиди. Тестові файли також можуть визначати:
BenchmarkXxx(b *testing.B)— бенчмарки продуктивності.FuzzXxx(f *testing.F)— fuzz-тести.ExampleXxx()— запустимі приклади, що одночасно служать документацією.
go.mod — як виглядає кожна директива¶
go.mod — це рядково-орієнтований текстовий файл у кодуванні UTF-8. Повний приклад із кожною директивою:
module example.com/myapp
go 1.23.0
toolchain go1.23.4
require (
github.com/gorilla/mux v1.8.1
golang.org/x/crypto v0.21.0 // indirect
)
exclude github.com/some/pkg v1.4.0
replace github.com/some/pkg => ../local/pkg
retract v1.0.1 // do not depend on this version of MY module
godebug panicnil=1
| Директива | Призначення |
|---|---|
module |
Канонічний шлях імпорту модуля. Використовується рівно один раз. |
go |
Мінімальна версія мови Go, якої потребує цей модуль. |
toolchain |
Рекомендована версія toolchain для розробки та CI. |
require |
Залежність у конкретній мінімальній версії. // indirect позначає транзитивні залежності. |
exclude |
Відхилити конкретну версію залежності. |
replace |
Перенаправити модуль на локальний шлях або форк. |
retract |
Позначити версії власного модуля як ті, що не слід використовувати. |
godebug |
Зафіксувати перемикач GODEBUG, коли цей модуль є головним. |
tool |
Оголосити інструмент Go, запустити який можна через go tool. |
Не редагуйте go.mod вручну для рутинних змін. Використовуйте go get, go mod tidy тощо — вони знають про go.sum і збережуть обидва файли узгодженими.
go.sum — як він виглядає¶
Два рядки на кожну пару (module, version):
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
- Перший рядок: хеш повного zip-архіву модуля.
- Другий рядок: хеш лише файлу
go.modцього модуля.
Другий рядок дозволяє Go перевіряти транзитивні метадані без завантаження відповідних модулів. Обидва рядки записуються та перевіряються командою go автоматично. Ніколи не редагуйте go.sum вручну.