Модуль
1Пакеты: основы2Go модули3Тестирование4Инструменты Go← вы здесь
Урок 4~12 минут

Инструменты Go

Экосистема инструментов Go

Одно из достоинств Go — богатая стандартная экосистема. Многое встроено в go команду, остальное — де-факто стандарты сообщества.


gofmt: форматирование без споров

В большинстве команд разработчики тратят время на споры о форматировании: табы или пробелы, где ставить скобки. В Go этого нет — есть один стандарт и инструмент gofmt:

bash
# Показать diff (не изменять файлы)
gofmt -d main.go
 
# Отформатировать файл
gofmt -w main.go
 
# Отформатировать весь проект
gofmt -w .

goimports — улучшенный gofmt который ещё и управляет импортами:

bash
go install golang.org/x/tools/cmd/goimports@latest
goimports -w .

В IDE (VS Code + gopls, GoLand) форматирование применяется автоматически при сохранении файла. Настрой это с первого дня — код всегда будет выглядеть одинаково.


go vet: статический анализ

go vet ловит подозрительный код без запуска программы:

bash
go vet ./...

Что находит:

go
// Неверный формат printf
fmt.Printf("%d", "строка")          // vet: arg "строка" has wrong type
 
// Копирование мьютекса (должен передаваться по указателю)
mu := sync.Mutex{}
mu2 := mu                            // vet: assignment copies lock value
 
// Unreachable code
func f() int {
    return 1
    fmt.Println("недостижимо")       // vet: unreachable code
}
 
// Неверное использование atomic
var x int64
atomic.AddInt64(&x, 1)
y := x                               // vet: data race на x без atomic

go vet — обязательный шаг перед коммитом. Большинство CI конфигураций запускают его автоматически.


golangci-lint: всё сразу

golangci-lint запускает 50+ линтеров параллельно — быстро и удобно:

bash
# Установка
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
 
# Запуск
golangci-lint run ./...

Конфигурация .golangci.yml:

yaml
linters:
  enable:
    - govet        # встроенный go vet
    - errcheck     # проверяет что ошибки не игнорируются
    - staticcheck  # мощный статический анализ
    - gosimple     # упрощения кода
    - ineffassign  # присваивания которые никогда не используются
    - unused       # неиспользуемый код
    - gofmt        # форматирование
    - goimports    # импорты
    - misspell     # опечатки в комментариях
    - revive       # замена golint
 
linters-settings:
  errcheck:
    check-blank: true  # даже _ = riskyFunc()
 
issues:
  max-same-issues: 3

Запускай в CI на каждый pull request — это стандарт в Go-проектах.


staticcheck: умный анализатор

staticcheck — один из лучших статических анализаторов для Go:

bash
go install honnef.co/go/tools/cmd/staticcheck@latest
staticcheck ./...

Что находит сверх go vet:

go
// Устаревшие API
ioutil.ReadFile(...)    // SA1019: ioutil.ReadFile is deprecated, use os.ReadFile
 
// Бесполезные операции
strings.Replace(s, "a", "b", 0)  // SA4009: n=0 означает "не заменять"
 
// Неправильное использование sync
var wg sync.WaitGroup
wg.Add(1)
go func() { wg.Done() }()
wg.Wait()
wg.Add(1)  // SA2001: после Wait() — возможная гонка
 
// Неиспользуемые параметры функции
func process(ctx context.Context, data []byte) {
    // ctx не используется вообще
    return process2(data)
}

go doc: документация в терминале

Go генерирует документацию из комментариев. Соглашение: комментарий начинается с имени того что документирует:

go
// User представляет пользователя системы.
// Используй NewUser для создания валидного экземпляра.
type User struct {
    ID    int
    Email string
}
 
// NewUser создаёт нового пользователя с валидацией email.
// Возвращает ошибку если email невалиден.
func NewUser(email string) (*User, error) {
    // ...
}
bash
# Документация пакета
go doc ./user
 
# Конкретная функция
go doc ./user NewUser
 
# Стандартная библиотека
go doc fmt.Println
go doc net/http.Client
 
# Локальный сервер документации
go install golang.org/x/tools/cmd/godoc@latest
godoc -http=:6060
# открой http://localhost:6060

pprof: профилировщик

Когда программа работает медленно или ест много памяти — pprof:

go
import (
    "net/http"
    _ "net/http/pprof"  // blank import регистрирует эндпоинты
)
 
func main() {
    go http.ListenAndServe(":6060", nil)
    // ...основной код
}
bash
# CPU профиль (30 секунд)
go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30
 
# Heap профиль
go tool pprof http://localhost:6060/debug/pprof/heap
 
# Горутины
go tool pprof http://localhost:6060/debug/pprof/goroutine
 
# Интерактивный режим:
(pprof) top10          # топ функций по CPU/памяти
(pprof) list funcName  # построчно
(pprof) web            # граф вызовов в браузере

Для тестов встроен бенчмарк-профайлер:

bash
go test -bench=. -cpuprofile=cpu.out -memprofile=mem.out
go tool pprof cpu.out

go generate: кодогенерация

go generate запускает команды указанные в комментариях к коду:

go
// В файле models.go:
//go:generate stringer -type=Direction
type Direction int
 
const (
    North Direction = iota
    South
    East
    West
)
bash
go generate ./...
# Запустит: stringer -type=Direction
# Создаст: direction_string.go с методом String()

Популярные кодогенераторы:

  • stringer — методы String() для enum-подобных типов
  • mockgen — моки для интерфейсов
  • protoc-gen-go — код из protobuf схем
  • sqlc — типобезопасный код из SQL запросов

Минимальный CI для Go проекта

yaml
# .github/workflows/go.yml
name: Go
 
on: [push, pull_request]
 
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-go@v5
        with:
          go-version: '1.22'
 
      - name: Vet
        run: go vet ./...
 
      - name: Test
        run: go test -race -cover ./...
 
      - name: Lint
        uses: golangci/golangci-lint-action@v4

-race включает детектор гонок — обязателен в CI. Находит data race которые иначе проявятся только в продакшне.

gofmt — форматирование без споров. go vet — ловит баги до запуска. golangci-lint — 50+ линтеров одной командой. staticcheck — лучший статический анализатор. Настрой всё это в CI с первого дня.

gofmt форматирует Go код по единому стандарту. Никаких споров о стиле — один стандарт для всей экосистемы.

До не форматировано
package main
import "fmt"
func   add(a  int,b int)int{
return a+b
}
func main(){
  x:=add(1,2)
   fmt.Println(x)
}
После
package main
import "fmt"
func   add(a  int,b int)int{
return a+b
}
func main(){
  x:=add(1,2)
   fmt.Println(x)
}
🎯
Миссия 1 из 4
Какая команда форматирует Go код по стандарту?