Система пакетов Go
Пакет (package) — основная единица организации кода в Go. Каждый файл .go принадлежит ровно одному пакету.
Правила пакетов
// File: math/calculator.go
package math // Every file in a directory must have the same package name
import "fmt"
// Exported — starts with UPPERCASE (visible outside the package)
func Add(a, b int) int {
return a + b
}
// Unexported — starts with lowercase (private to the package)
func validate(n int) bool {
return n >= 0
}
// Exported type with mixed visibility
type Calculator struct {
Name string // Exported field
history []int // Unexported field
}
// Exported method
func (c *Calculator) Compute(expr string) (int, error) {
result := 42 // Simplified
c.history = append(c.history, result)
return result, nil
}
// Unexported method
func (c *Calculator) reset() {
c.history = nil
}
| Правило | Описание |
|---|---|
| Имя пакета | Совпадает с именем директории (по конвенции) |
| Один пакет — одна директория | Все файлы в директории должны иметь одно имя пакета |
| Экспорт через регистр | Заглавная буква = экспортировано, строчная = приватно |
package main |
Специальный пакет для создания исполняемых файлов |
| Неиспользуемый импорт | Ошибка компиляции |
Правила именования пакетов
// GOOD package names:
package http // Short, lowercase, no underscores
package json
package user // Singular, not users
package strconv // Abbreviation is OK if widely known
// BAD package names:
package httpUtils // Don't use camelCase
package http_util // Don't use underscores
package common // Too vague
package utils // Too vague
package base // Too vague
package models // Avoid plural
Go Proverb: Имя пакета — это часть имени каждого экспортируемого идентификатора.
http.Server, а неhttp.HTTPServer. Избегайте заикания (stuttering).
Импорт пакетов
package main
import (
// Standard library
"fmt"
"io"
"net/http"
// Third-party (grouped separately by convention)
"github.com/gorilla/mux"
// Internal/local packages
"github.com/myorg/myapp/internal/service"
)
// Named import — resolve name conflicts
import (
"crypto/rand" // Package name: rand
mathrand "math/rand" // Alias to avoid conflict
)
// Dot import — imports into current namespace (avoid!)
import . "fmt"
// Now you can call Println() instead of fmt.Println()
// NEVER use in production code — only in tests sometimes
// Blank import — import for side effects only
import _ "image/png" // Registers PNG decoder via init()
// Blank import is common for:
// - Database drivers: _ "github.com/lib/pq"
// - Image decoders: _ "image/jpeg"
// - Profiling: _ "net/http/pprof"
Go Modules
Go Modules (с Go 1.11, по умолчанию с Go 1.16) — официальная система управления зависимостями.
Создание модуля
# Initialize a new module
mkdir myproject && cd myproject
go mod init github.com/username/myproject
# This creates go.mod:
// go.mod
module github.com/username/myproject
go 1.25
require (
github.com/gorilla/mux v1.8.1
golang.org/x/sync v0.7.0
)
require (
// Indirect dependencies (automatically managed)
golang.org/x/text v0.16.0 // indirect
)
Файлы go.mod и go.sum
| Файл | Назначение |
|---|---|
go.mod |
Определение модуля, зависимости и их версии |
go.sum |
Криптографические хэши зависимостей для воспроизводимости |
// go.sum (generated automatically, DO NOT edit manually)
github.com/gorilla/mux v1.8.1 h1:TuMoUvkRETW...
github.com/gorilla/mux v1.8.1/go.mod h1:DVbg23sWS...
Важно:
go.sumобязательно должен быть в системе контроля версий. Он гарантирует, что все разработчики и CI используют идентичные зависимости.
Основные команды
# Add a dependency
go get github.com/gorilla/[email protected]
# Add latest version
go get github.com/gorilla/mux@latest
# Update a dependency
go get -u github.com/gorilla/mux
# Update all dependencies
go get -u ./...
# Remove unused dependencies, add missing ones
go mod tidy
# Download dependencies to local cache
go mod download
# Copy dependencies to vendor/ directory
go mod vendor
# Verify dependency checksums
go mod verify
# Show dependency graph
go mod graph
# Explain why a module is needed
go mod why github.com/gorilla/mux
# Show available versions
go list -m -versions github.com/gorilla/mux
Версионирование (Semantic Versioning)
Go Modules строго следуют Semantic Versioning (semver):
v1.2.3
│ │ │
│ │ └── Patch: bug fixes, no API changes
│ └──── Minor: new features, backward compatible
└────── Major: breaking changes
| Версия | Импорт | Описание |
|---|---|---|
| v0.x.x | github.com/user/pkg |
Нестабильная, API может меняться |
| v1.x.x | github.com/user/pkg |
Стабильная, обратная совместимость |
| v2.x.x | github.com/user/pkg/v2 |
Несовместимые изменения, новый путь |
| v3.x.x | github.com/user/pkg/v3 |
Каждый major — новый путь импорта |
v2+ Convention
// go.mod for v2
module github.com/user/mylib/v2
go 1.25
// Importing v2
import "github.com/user/mylib/v2"
// You can use v1 and v2 simultaneously!
import (
v1 "github.com/user/mylib"
v2 "github.com/user/mylib/v2"
)
Это называется Import Compatibility Rule: если путь импорта одинаков, код должен быть совместим.
Директива replace
replace позволяет подменить модуль другим — полезно для локальной разработки:
// go.mod
module github.com/myorg/myapp
go 1.25
require (
github.com/myorg/mylib v1.2.0
)
// Replace with a local path (for development)
replace github.com/myorg/mylib => ../mylib
// Replace with a fork
replace github.com/original/pkg => github.com/myfork/pkg v1.0.0
// Replace with a specific version
replace golang.org/x/crypto => golang.org/x/crypto v0.23.0
Важно:
replaceработает только вgo.modглавного модуля. Зависимости не наследуют чужиеreplaceдирективы.
Директива exclude и retract
// go.mod
// Exclude a broken version
exclude github.com/broken/pkg v1.3.0
// Retract versions of YOUR module (Go 1.16+)
retract (
v1.0.0 // Published with critical bug
[v1.1.0, v1.2.0] // Range of retracted versions
)
Go Workspaces (Go 1.18+)
Workspaces позволяют работать с несколькими модулями одновременно без replace директив.
# Project structure:
# workspace/
# ├── go.work
# ├── myapp/
# │ ├── go.mod
# │ └── main.go
# └── mylib/
# ├── go.mod
# └── lib.go
# Create workspace
cd workspace
go work init
# Add modules to workspace
go work use ./myapp
go work use ./mylib
# Or add both at once
go work use ./myapp ./mylib
Файл go.work:
go 1.25
use (
./myapp
./mylib
)
// Optional: replace directives (workspace-level)
// replace github.com/someorg/somepkg => ./local-somepkg
| Аспект | replace | go.work |
|---|---|---|
| Где объявляется | В go.mod |
В go.work |
| Коммитится в git | Не рекомендуется (для dev) | Не коммитится (обычно) |
| Область действия | Один модуль | Все модули в workspace |
| Цель | Подмена зависимости | Мультимодульная разработка |
# Workspace commands
go work init # Create go.work
go work use ./path # Add a module
go work sync # Sync go.work with module dependencies
go work edit # Edit go.work programmatically
# Build/test all modules in workspace
go build ./...
go test ./...
Совет:
go.workобычно НЕ коммитится в git (добавляется в.gitignore). Он нужен только для локальной разработки.
Internal packages
Директория internal в Go имеет специальное значение на уровне компилятора:
myproject/
├── go.mod
├── cmd/
│ └── server/
│ └── main.go # Can import internal/
├── internal/
│ ├── auth/
│ │ └── auth.go # Only importable from myproject/...
│ └── database/
│ └── db.go
├── pkg/
│ └── api/
│ └── api.go # Importable by anyone
└── other-project/
└── main.go # CANNOT import myproject/internal/...
// myproject/cmd/server/main.go
package main
import (
"github.com/myorg/myproject/internal/auth" // OK
"github.com/myorg/myproject/internal/database" // OK
"github.com/myorg/myproject/pkg/api" // OK
)
// another-project/main.go
import (
"github.com/myorg/myproject/internal/auth" // COMPILE ERROR!
"github.com/myorg/myproject/pkg/api" // OK
)
Правило: internal доступен только коду, находящемуся в дереве родительской директории internal.
Vendor directory
# Create vendor directory with all dependencies
go mod vendor
# Build using vendor instead of module cache
go build -mod=vendor ./...
# Verify vendor is consistent
go mod verify
| Аспект | Module cache | Vendor |
|---|---|---|
| Расположение | $GOPATH/pkg/mod |
./vendor/ |
| Общий для проектов | Да | Нет |
| Коммитится в git | Нет | Иногда (для автономности) |
| Используется по умолчанию | Да | Нет (нужен -mod=vendor) |
Практические паттерны
Организация пакетов по функциональности
// GOOD: organized by domain/functionality
myapp/
├── user/
│ ├── handler.go // HTTP handlers
│ ├── service.go // Business logic
│ ├── repository.go // Data access
│ └── model.go // Types
├── order/
│ ├── handler.go
│ ├── service.go
│ └── repository.go
└── pkg/
└── middleware/
└── auth.go
// BAD: organized by layer (Java-style)
myapp/
├── handlers/
│ ├── user.go
│ └── order.go
├── services/
│ ├── user.go
│ └── order.go
├── models/
│ ├── user.go
│ └── order.go
└── repositories/
├── user.go
└── order.go
Go Proverb: "A little copying is better than a little dependency." Не создавайте пакет
utils— скопируйте маленькую функцию туда, где она нужна.