1209551
📖 Tutorial

How to Use Go’s Source-Level Inliner for Effortless Code Modernization

Last updated: 2026-05-09 15:41:27 Intermediate
Complete guide
Follow along with this comprehensive guide

Introduction

Keeping your Go codebase up-to-date with the latest language and library APIs can be tedious and error-prone. Go 1.26 introduces a revamped go fix subcommand that includes a powerful source-level inliner – a self-service tool that lets any package author define simple API migrations and apply them automatically across their project. This guide walks you through using the source-level inliner, whether via go fix or gopls, to modernize your code safely and efficiently.

How to Use Go’s Source-Level Inliner for Effortless Code Modernization
Source: blog.golang.org

What You Need

  • Go 1.26 or later – The source-level inliner is built into the new go fix and is also available via gopls. Install the latest version from go.dev/dl.
  • An editor with gopls support (recommended) – For interactive refactoring, use VS Code, Vim, Emacs, or any editor that integrates with the Go language server.
  • A Go module – The tool works on any module; ensure your project uses Go modules (go.mod file present).
  • Basic familiarity with Go functions and packages – No advanced knowledge required, but understanding function calls and parameters helps.

Step-by-Step Guide

Step 1: Understand What Source-Level Inlining Does

Source-level inlining replaces a function call with a copy of the function’s body, substituting arguments for parameters. Unlike compiler inlining (which works on intermediate representation), this transformation is applied directly to your source code. It preserves all original comments and formatting. The inliner is used by gopls for refactorings like “Inline call” and by the new go fix for automated API migrations. For example, if you have a small helper function sum(a, b int) int { return a + b } and a call six := sum(3, 3), inlining would produce six := 3 + 3.

Step 2: Set Up Your Environment

Ensure you are using Go 1.26+. Verify with:
go version
If you plan to use the interactive inliner, make sure gopls is up to date:
go install golang.org/x/tools/gopls@latest
Restart your editor to pick up the new version.

Step 3: Invoke the Source-Level Inliner via go fix

The new go fix includes a built-in analyzer for source-level inlining. To apply it across your entire module, run:

go fix ./...

This will scan for all functions tagged with the special directive //go:fix inline (placed just before the function declaration) and inline every call to those functions throughout your module. You can also target a specific package:
go fix ./pkg/...
The changes are applied in-place. Always commit or backup your code before running such automated transformations.

Step 4: Use the Interactive Inliner in Your Editor

If you prefer to inline calls one at a time or test the transformation before committing, use gopls’s interactive refactoring:

  1. Open a Go file in your editor.
  2. Place your cursor on a function call you wish to inline.
  3. Open the “Source Action…” menu (in VS Code, this is Ctrl+. under the lightbulb icon, or via the Command Palette).
  4. Select “Inline call” (or “Inline function call”).
  5. The call is replaced inline. Review the result and save the file.

This method is great for one-off refactorings or when you want to understand exactly what changes are made.

Step 5: Tagging Functions for Automated Inlining with //go:fix inline

Package authors can mark functions that should be automatically inlined by go fix. Add a comment directive immediately before the function declaration:

//go:fix inline
func sum(a, b int) int {
    return a + b
}

When you run go fix ./... later, all calls to sum in your module will be replaced by the body of sum with actual arguments substituted. This is especially useful for migrating away from deprecated wrappers or simplifying code after an API change.

How to Use Go’s Source-Level Inliner for Effortless Code Modernization
Source: blog.golang.org

Step 6: Review and Validate the Changes

After running go fix, inspect the diff using your version control system:

git diff

Check that:

  • All intended calls were inlined and unintended ones were not.
  • The resulting code compiles (go build ./...).
  • Tests still pass (go test ./...).
  • Comments and formatting are preserved.

If something looks off, restore the backup and adjust the tagging or run the interactive inliner on specific calls.

Step 7: Understand the Correctness Guarantees

The source-level inliner handles many edge cases automatically:

  • Variable shadowing – It renames variables to avoid conflicts with the outer scope.
  • Side effects in arguments – If an argument expression has side effects (e.g., f() + g()), the inliner preserves evaluation order by introducing temporary variables.
  • Return statements – Inlined functions with early returns are transformed into equivalent code using local variables and control flow.
  • Deferred calls and closures – These are handled with care to maintain correct semantics.

You do not need to worry about these details – the tool does it for you.

Tips for Success

  • Start small: Before running go fix on your entire module, test it on a single package or run it with go fix -v ./... to see which files are affected.
  • Combine with version control: Always commit or stash your changes before applying automated transformations. This makes it easy to revert if needed.
  • Use annotations judiciously: Only tag functions that are simple enough to inline safely (e.g., trivial getters, wrappers, or deprecated helpers). Complex functions may lead to code bloat or subtle bugs.
  • Leverage gopls for learning: If you are unsure how inlining will affect a call, use the interactive “Inline call” refactoring first. The preview helps you understand the transformation.
  • Keep documentation updated: After inlining, remove the original function if it is no longer used, and update any comments that referred to it.
  • Monitor performance: Excessive inlining can increase binary size. Use the compiler’s inlining heuristics as a guide – source-level inlining is best for readability and maintenance, not optimizations.

By following these steps, you can modernize your Go code with confidence, automate tedious API migrations, and take full advantage of the new go fix infrastructure. Happy coding!