# gofmt и go vet

> Встроенные инструменты Go — gofmt приводит код к единственному каноническому формату, go vet находит подозрительные конструкции; вместе с staticcheck и golangci-lint они составляют стандартный набор проверок Go-проекта.

Источник: https://llmdocs.ru/wiki/gofmt-govet/ · обновлено 2026-11-09 · лицензия CC BY-SA 4.0

- **Язык**: Go
- **gofmt**: форматирование, без настроек
- **go vet**: статический анализ подозрительного кода
- **Поставляются**: вместе с Go (go fmt, go vet)
- **Сторонние**: goimports, staticcheck, golangci-lint, gofumpt
- **Интеграция**: gopls (сервер языка), pre-commit, CI
**gofmt** и **go vet** — два инструмента, которые поставляются вместе с [Go](https://llmdocs.ru/wiki/go.md). `gofmt` автоматически приводит исходный код к единственному каноническому виду, а `go vet` ищет конструкции, которые компилируются, но почти наверняка являются ошибками. Они задали культуру Go-сообщества: споры о стиле закончились, потому что стиль один, а базовый статический анализ запускается одной командой без настройки.[1][2]

## gofmt

`gofmt` появился одновременно с языком в 2009 году. Его ключевая особенность — **отсутствие настроек**: нет выбора между табами и пробелами, нет длины строки, нет вариантов расстановки скобок. Отступы — табы, выравнивание — пробелы, открывающая фигурная скобка — на той же строке (это требует и сам синтаксис из-за автоматической вставки точек с запятой).[4] Роб Пайк сформулировал это так: «стиль gofmt никому не нравится, но gofmt нравится всем».[3]

```bash
gofmt -l .        # список файлов, которые отформатированы не так
gofmt -d main.go  # показать diff
gofmt -w .        # переписать файлы на месте
go fmt ./...      # то же для всех пакетов модуля (gofmt -l -w)
gofmt -s -w .     # дополнительно упростить код
```

Флаг `-s` упрощает выражения: например, `[]T{T{1}, T{2}}` превращается в `[]T{{1}, {2}}`, а `s[a:len(s)]` — в `s[a:]`. Флаг `-r` позволяет делать механические замены по шаблону: `gofmt -r 'bytes.Compare(a, b) == 0 -> bytes.Equal(a, b)' -w .`.

Поскольку формат детерминирован, `gofmt` безопасно запускать автоматически: при сохранении в редакторе (через сервер языка **gopls**), в pre-commit и в [CI/CD](https://llmdocs.ru/wiki/ci-cd.md). Диффы в ревью содержат только смысловые изменения. Идея оказалась заразительной: rustfmt в Rust (см. [Clippy и rustfmt](https://llmdocs.ru/wiki/clippy-rustfmt.md)), Black и [Ruff](https://llmdocs.ru/wiki/ruff.md) в Python, Prettier в JavaScript переняли подход «форматтер без споров».

### goimports и gofumpt

- **goimports** делает всё то же, что gofmt, и дополнительно добавляет недостающие и удаляет неиспользуемые импорты, группируя стандартную библиотеку отдельно. Многие редакторы используют именно его.
- **gofumpt** — более строгий форматтер-надмножество: убирает лишние пустые строки, объединяет объявления и т. п. Его результат по-прежнему совместим с gofmt.

## go vet

`go vet` — статический анализатор, который проверяет корректность, а не стиль. Он запускается как `go vet ./...` и, что важно, автоматически выполняет часть проверок при `go test`.[2] Набор анализаторов включает:

| Анализатор | Что ловит |
|---|---|
| `printf` | несоответствие формата и аргументов в `fmt.Printf("%d", "строка")` |
| `copylocks` | копирование `sync.Mutex` по значению |
| `loopclosure` | захват переменной цикла в горутине (актуально до Go 1.22) |
| `lostcancel` | `context.WithCancel` без вызова `cancel` |
| `structtag` | некорректные теги полей вроде `json:name` без кавычек |
| `unreachable` | недостижимый код |
| `httpresponse` | использование `resp.Body` до проверки ошибки |
| `nilfunc`, `bools`, `assign` | бессмысленные сравнения и присваивания |
| `unusedresult` | игнорирование результата чистых функций вроде `fmt.Sprintf` |

Пример, который скомпилируется, но vet отклонит:

```go
var mu sync.Mutex
func f(m sync.Mutex) {}   // vet: f passes lock by value
fmt.Printf("%s\n", 42)    // vet: Printf format %s has arg 42 of wrong type int
```

Анализаторы построены на общем фреймворке `golang.org/x/tools/go/analysis`, поэтому их легко комбинировать и писать собственные.[7] Отдельно стоит детектор гонок `-race` — он не статический, а работает во время выполнения тестов (см. [Состояние гонки и блокировки](https://llmdocs.ru/wiki/race-conditions-locks.md)).

## Более строгие линтеры

`go vet` намеренно консервативен: в нём только проверки почти без ложных срабатываний. Для большего используют:

- **staticcheck** — самый известный сторонний анализатор: ошибки (SA), упрощения (S), стиль (ST), устаревшие API; многие его проверки в итоге попадают в gopls.[5]
- **golangci-lint** — агрегатор, который запускает десятки линтеров (vet, staticcheck, errcheck, gosec, revive, ineffassign и др.) параллельно, с общим кэшем и одним конфигом `.golangci.yml`.[6] Это стандарт де-факто для CI.

```yaml
# .golangci.yml (фрагмент)
version: "2"
linters:
  enable: [errcheck, govet, staticcheck, gosec, revive]
formatters:
  enable: [gofumpt, goimports]
```

Линтер **errcheck** особенно полезен: он находит проигнорированные ошибки, что для Go с его явной [обработкой ошибок](https://llmdocs.ru/wiki/go-errors.md) — частый источник багов.

## В CI

Типичная проверка в пайплайне [GitHub Actions](https://llmdocs.ru/wiki/github-actions.md):

```bash
test -z "$(gofmt -l .)"   # упасть, если что-то не отформатировано
go vet ./...
golangci-lint run
go test -race ./...
```

Набор из форматтера, vet, линтера и тестов с `-race` дёшев и покрывает большую часть типовых ошибок ещё до ревью.

## См. также

- [Тестирование в Go](https://llmdocs.ru/wiki/go-testing.md)
- [Стандартная библиотека Go](https://llmdocs.ru/wiki/go-stdlib.md)
- [Clippy и rustfmt](https://llmdocs.ru/wiki/clippy-rustfmt.md)
- [Ruff](https://llmdocs.ru/wiki/ruff.md)

## Источники

1. [Go — Command gofmt](https://pkg.go.dev/cmd/gofmt)
2. [Go — Command vet](https://pkg.go.dev/cmd/vet)
3. [Go Blog — go fmt your code](https://go.dev/blog/gofmt)
4. [Effective Go — Formatting](https://go.dev/doc/effective_go#formatting)
5. [Staticcheck documentation](https://staticcheck.dev/docs/)
6. [golangci-lint documentation](https://golangci-lint.run/)
7. [Go — golang.org/x/tools/go/analysis](https://pkg.go.dev/golang.org/x/tools/go/analysis)
