| name | go-refactoring |
| description | Safe Go refactoring patterns using gopls, golangci-lint, and incremental compilation. Use when moving code between packages, renaming types/functions, or extracting modules. |
Go Refactoring with LSP Tools
Available Tools
gopls — Go Language Server (type-safe rename, find references, implementations)
golangci-lint — Meta-linter (catches what go vet misses)
goimports — Auto-fix imports after moving code (part of gotools)
Golden Rule
Never use sed for Go refactoring. Use gopls for renames and the edit tool for surgical changes. Run go build ./... after EVERY change.
Refactoring Patterns
Moving Functions Between Packages
- Create the new file in the target package
- Copy the function (don't cut yet)
- Update the signature — export if needed, adjust receiver types
- Run
go build ./... — fix import paths
- Update all callers to use the new package
- Run
go build ./... again — verify callers compile
- Delete the old function
- Run
go build ./... && go test ./... — final check
Type-Safe Rename with gopls
gopls rename -w path/to/file.go:#OFFSET NewName
grep -b 'oldFunctionName' path/to/file.go
Find All References
gopls references path/to/file.go:#OFFSET
Extract Method to New Package — Step by Step
mkdir -p internal/newpkg
gopls references internal/controller/old_file.go:#OFFSET
go build ./...
goimports -w internal/controller/old_file.go
goimports -w internal/newpkg/new_file.go
go build ./... && go test ./...
Lint After Refactoring
golangci-lint run ./...
golangci-lint run ./internal/newpkg/... ./internal/controller/...
Anti-Patterns
❌ sed -i 's/oldFunc/newFunc/g' *.go — breaks string literals, comments, partial matches
❌ Making 10 changes then building — cascading errors become impossible to debug
❌ Moving code without checking references first — orphaned callers
❌ Skipping goimports after cross-package moves — import hell
Incremental Refactoring Checklist
For each function/method being moved: