TGViewer
Go Update Go Update @go_update · 3.23K subscribers
Post #124 2.15K
✍️ go fix: apply fixes from modernizers ✍️

Есть такая утилита в тулчейне Go — go fix. В задачу которой входила модернизация кода под новые конструкции — как в языке, так и в стандартной библиотеке. Эдакий аналог go fmt который вместо единого стиля, выравнивал использования языковых конструкций по кодобазе. И вроде отличная идея, но с одной проблемой: почти десять лет никто её не поддерживал и не модернизировал. Те сама утилита осталась в далеких временах Go 1.8. Причина подобного довольно тривиальна: нет необходимости в обобщенной модернизации кода, а значит нет и свободных ресурсов под это. Тем более сам go fix был написан с использованием большого числа костылей, которые усложняли любую попытку модернизации.

Однако всё изменилось с приходом LLM: модели OpenAI, Anthropic, Alibaba и прочих обучаются на огромных массивах данных в свободном доступе и код генерируют исходя из увиденного. И тут стало понятно: если модели всегда будут учится на старом коде, то и предлагать они будут всегда старые паттерны. Поэтому, недавно вернувшийся в Google, Алан Донован (да-да, тот самый от кого у вас та самая голубая книжка) всерьез озаботился вопросом модернизации кода.

Первый шаг — пускаем старый кода под нож. Полностью.
Второй шаг — это полная переделка команды на основе различных анализаторов из gopls. Которые, в свою очередь, используют фреймворк analysis.

Результат: у нас есть «модернизатор» кода который заменяет «устаревшие» паттерны их современными аналогами.

Приведу несколько примеров. Начиная с 1.26 подъехал новый синтаксис new который умеет в значения. А модернизатор умеет распознавать где он нужен:


data, err := json.Marshal(&RequestJSON{
URL: url,
Attempts: newInt(10),
})

func newInt(x int) *int { return &x }


Становится


data, err := json.Marshal(&RequestJSON{
URL: url,
Attempts: new(10),
})


Тоже самое касаемо использования конкатенации строк внутри циклов:


s := ""
for _, b := range bytes {
s += fmt.Sprintf("%02x", b)
}
use(s)


Становится


var s strings.Builder
for _, b := range bytes {
s.WriteString(fmt.Sprintf("%02x", b))
}
use(s.String())


Те из коробки мы получаем и более краткий и более производительный код. Еще одна фича, которая доступна ещё и «обычным смертным»: новая аннотация //go:fix inline которая позволяет проводить inlining функций. Те если go fix встроен в ваш пайплайн, все перестановки произойдут автоматически, что удобно когда у вас был большой рефакторинг и внешних пользователей надо уведомить о новом расположении (или сигнатуре) функций.

Сама команда Go Core опубликовала отличные статьи которые показывают паттерны использования нового функционала и внутрянку того, как это работает. Рекомендую к прочтению.
go.dev Introducing Gofix - The Go Programming Language How to use go fix to update your code with each new Go release.
  • 👍 10
  • 🔥 7
  • ❤ 4
More from @go_update
  1. Aug 22, 2026Об изоляции LLM Да, это ещё один пост про работу с Codex/Claude/GLM/Qwen/DeepSeek и прочая…
  2. Aug 11, 2026И вот эти два минуса выглядят нерешенными (на данный момент времени). Можно ли их решить в…
  3. Aug 11, 2026🎂 Вечерний пост о том, что сегодня мне исполнилось 34. Прошёл еще один год, а значит врем…
  4. Jul 13, 2026📝 testing: allow examples with any signature Небольшое «Quality of Life» предложение. Сут…
  5. May 14, 2026📝 net/http/httptest: synctest support Я уже писал про пакет synctest и его возможности. Э…
  6. May 13, 2026Я редко пишу сюда о вещах которые не относятся к Go, но тут у меня появилась хорошая стать…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →