# Go Rename > Complete API reference for the`golang.org/x/tools/refactor/rename`package. --- # Source: https://pkg.go.dev/golang.org/x/tools/refactor/rename # Go Rename API Reference Complete API reference for the `golang.org/x/tools/refactor/rename` package. ## Package Overview ```go import "golang.org/x/tools/refactor/rename" ``` The rename package provides identifier renaming functionality for Go source code. **Module:** `golang.org/x/tools` **Version:** v0.40.0 **License:** BSD-3-Clause ## Constants None exported at the package level. ## Variables ### Configuration Variables ```go var ( // Force controls whether to patch files even if conflicts exist Force bool // Diff enables diff mode - displays diffs instead of rewriting files Diff bool // DiffCmd specifies the diff command to use DiffCmd string = "diff" // Verbose enables extra logging output Verbose bool ) ``` ### Error Variables ```go var ConflictError error ``` Returned when renaming aborts due to identifier conflicts. ## Functions ### Main ```go func Main(ctxt *build.Context, offsetFlag, fromFlag, to string) error ``` **Purpose:** Entry point for the rename operation. **Parameters:** - `ctxt` (*build.Context) - Build context specifying compilation environment - `offsetFlag` (string) - Location of identifier to rename (format: `file:#offset` or `file:#line:column`) - `fromFlag` (string) - Import path context for the identifier - `to` (string) - New name for the identifier **Returns:** Error if operation fails, including ConflictError if conflicts detected. **Example:** ```go import ( "go/build" "golang.org/x/tools/refactor/rename" ) ctx := build.Default err := rename.Main(&ctx, "main.go:#142", "", "newName") if err != nil { log.Fatal(err) } ``` ### Move ```go func Move(ctxt *build.Context, from, to, moveTmpl string) error ``` **Purpose:** Moves a package from one import path to another, updating all imports. **Parameters:** - `ctxt` (*build.Context) - Build context for the operation - `from` (string) - Current import path of package to move - `to` (string) - New import path for the package - `moveTmpl` (string) - Template string for constructing moved paths **Returns:** Error if move operation fails. **Functionality:** 1. Validates that destination path is available 2. Builds complete import graph of the codebase 3. Finds all imports of the package being moved 4. Updates all import statements 5. Relocates package files 6. Updates internal package references **Example:** ```go // Move github.com/old/path to github.com/new/path err := rename.Move(&build.Default, "github.com/old/path", "github.com/new/path", "") ``` ## Types ### ObjectSpec The rename logic operates on Go AST specifications: - Identifiers (variables, constants) - Functions and methods - Types (structs, interfaces, custom types) - Named imports ## Implementation Details ### Source Files | File | Purpose | |------|---------| | `rename.go` | Core renaming algorithm and identifier analysis | | `check.go` | Conflict detection and validation logic | | `mvpkg.go` | Package move functionality and import graph building | | `spec.go` | Go AST specification handling | | `util.go` | Utility functions for path handling and Go operations | ### How Renaming Works 1. **Parse**: Locate the identifier at the specified offset 2. **Analyze**: Determine identifier type and scope 3. **Search**: Find all references to the identifier 4. **Check**: Detect conflicts (name shadowing, collisions) 5. **Update**: Apply renaming to all files 6. **Write/Diff**: Either modify files or display diffs ### Import Graph For package-level operations, the rename package builds a complete import graph: ``` Package A imports Package B Package C imports Package B Package B imports Package D ... ``` This allows the tool to: - Find all packages importing a moved package - Update import statements consistently - Detect circular dependencies ## Error Handling ### ConflictError Returned when the rename operation detects conflicts: ```go if err := rename.Main(&ctx, offset, fromFlag, newName); err != nil { if err == rename.ConflictError { // Handle conflict - name already exists fmt.Println("Name conflict detected") } else { // Handle other errors log.Fatal(err) } } ``` ### Force Override When conflicts are detected, you can override with the Force flag: ```go rename.Force = true err := rename.Main(&ctx, offset, fromFlag, newName) ``` **Warning:** Force mode may produce incorrect code if there are legitimate conflicts. ## Type Safety Guarantees The rename package ensures: 1. **Scope Awareness**: Only renames identifiers in the correct scope 2. **Type Matching**: Ensures renamed identifier matches the original type 3. **Reference Tracking**: Updates all references, not just some 4. **Collision Detection**: Prevents renaming to names that would create conflicts 5. **Context Preservation**: Maintains identifier semantics ## Performance Characteristics ### Time Complexity - Building import graph: O(n) where n = number of files - Finding references: O(m) where m = total symbols in codebase - Updating references: O(r) where r = number of references ### Space Complexity - Maintains parse tree for all files: O(s) where s = total source size - Import graph: O(p) where p = number of packages ## Limitations - Does not work correctly with Go modules (deprecated) - Scope limited to the Go build context - May have issues with complex import patterns - No support for complex template-based refactoring ## Migration Path For modern development, migrate to **gopls**: ```bash # Old way (deprecated) gorename -offset file.go:#42 -to newName # New way (recommended) gopls rename file.go:42:0 newName ``` ## Related Packages - `golang.org/x/tools/go/loader` - Package loading and analysis - `golang.org/x/tools/refactor` - Refactoring utilities - `golang.org/x/tools/go/types` - Type checking - `golang.org/x/tools/go/ast` - AST utilities ## Build Constraints No special build constraints. Standard Go toolchain required. ## Thread Safety The rename package is **not thread-safe**. Access must be serialized if using from multiple goroutines. ## Deprecation Notice ⚠️ **This package is deprecated and will be removed in a future version.** **Reason:** Implementation has not worked properly since Go modules became standard. **Recommendation:** Use [gopls](https://github.com/golang/tools/tree/master/gopls) for all modern Go refactoring needs. ## Examples ### Simple Rename ```go package main import ( "go/build" "golang.org/x/tools/refactor/rename" ) func main() { ctx := build.Default // Rename oldFunc to newFunc at line 42, column 5 err := rename.Main(&ctx, "main.go:#42:5", "", "newFunc") if err != nil { panic(err) } } ``` ### Rename with Conflict Detection ```go func safeRename(filename string, offset int, newName string) error { ctx := build.Default rename.Diff = true // Preview changes first err := rename.Main(&ctx, filename + ":#" + string(rune(offset)), "", newName) if err == rename.ConflictError { return fmt.Errorf("conflict: name %s already exists", newName) } return err } ``` ### Move Package ```go func movePackage(oldPath, newPath string) error { ctx := build.Default return rename.Move(&ctx, oldPath, newPath, "") } ``` ## See Also - [gorename Command](https://pkg.go.dev/golang.org/x/tools/cmd/gorename) - [gopls - Go Language Server](https://pkg.go.dev/golang.org/x/tools/gopls) - [Go Build Package](https://pkg.go.dev/go/build) - [Go Parser](https://pkg.go.dev/go/parser) --- # Source: https://pkg.go.dev/golang.org/x/tools # Go Rename User Guide Comprehensive guide to using gorename for safe identifier refactoring in Go projects. ## Getting Started ### Installation Install gorename with the Go toolchain: ```bash go install golang.org/x/tools/cmd/gorename@latest ``` Verify installation: ```bash gorename -help ``` ### Quick Start The basic pattern is: ```bash gorename -offset : -to ``` Example: ```bash gorename -offset main.go:#142 -to NewName ``` ## Understanding Offsets gorename uses byte offsets to locate identifiers. The offset format has two variants: ### Variant 1: Byte Offset ```bash gorename -offset filename.go:# ``` - Byte offset from the start of the file - Useful for programmatic tools - Zero-indexed Example: ```bash # Rename identifier at byte 142 in main.go gorename -offset main.go:#142 -to newName ``` ### Variant 2: Line and Column ```bash gorename -offset filename.go:#: ``` - Line and column numbers (1-indexed) - More human-readable - Easier to use with editor information Example: ```bash # Rename identifier at line 42, column 5 in main.go gorename -offset main.go:#42:5 -to newName ``` ### Finding the Offset Use your editor to find line and column numbers: - **VS Code**: Position cursor on identifier, see "Ln X, Col Y" in status bar - **Vim**: Position on identifier, press `g` then `Ctrl+G` to see position - **Emacs**: `C-x =` displays position - **GoLand**: Hover over identifier to see position Or use tools to find offsets: ```bash # Show line numbers with grep grep -n "myFunction" main.go # Use sed to show positions sed -n '42p' main.go ``` ## Common Renaming Tasks ### Rename a Local Variable Local variables can be safely renamed within their scope: ```bash # In myfile.go at line 25, column 5, rename 'x' to 'count' gorename -offset myfile.go:#25:5 -to count # Preview first gorename -offset myfile.go:#25:5 -to count -diff ``` ### Rename a Function Functions can be renamed within a package. If exported, ensure all imports are updated: ```bash # Rename myFunc to calculateValue gorename -offset main.go:#100:6 -to calculateValue # For exported functions, gorename updates all imports ``` ### Rename a Type Renaming types (struct, interface, custom type) updates all usages: ```bash # Rename UserData type to User gorename -offset types.go:#15:6 -to User # All fields and methods are automatically renamed ``` ### Rename a Method Methods are renamed within their receiver type: ```bash # Rename String() method to Format() gorename -offset myfile.go:#50:6 -to Format ``` ### Rename a Package Rename a package by updating import paths: ```bash # Rename package 'util' to 'utilities' gorename -from "mypackage/util" -to "mypackage/utilities" # Updates all imports: import "mypackage/utilities" ``` ### Rename an Interface Interface renames update all implementations: ```bash # Rename Reader interface to InputReader gorename -offset types.go:#30:6 -to InputReader # All implementing types must satisfy new name ``` ## Preview Changes Before Applying Always preview changes on large refactorings: ```bash # Show diffs without modifying files gorename -offset main.go:#42:5 -to newName -diff # Examine output carefully # Only run without -diff if satisfied ``` ### Custom Diff Command Use a different diff tool: ```bash # Use meld for visual diff gorename -offset main.go:#42:5 -to newName -diff -diffcmd "meld" # Use vimdiff gorename -offset main.go:#42:5 -to newName -diff -diffcmd "vimdiff" ``` ## Advanced Usage ### Verbose Output Enable detailed logging: ```bash # Show what gorename is doing gorename -v -offset main.go:#42:5 -to newName ``` Output includes: - Files being processed - Conflicts detected - Progress of analysis - Statistics ### Force Override Conflicts When conflicts are detected, force the rename (not recommended): ```bash # Override conflict detection gorename -force -offset main.go:#42:5 -to newName ``` **Warning:** Using -force may produce incorrect code. Only use if you understand the implications. ### Handling Large Codebases For large projects, consider these strategies: 1. **Rename in stages**: Break large refactorings into smaller pieces 2. **Preview first**: Always use -diff on large changes 3. **Commit before renaming**: Ensure clean git state 4. **Test thoroughly**: Run tests after each rename ```bash # Safe workflow for large changes git add . && git commit -m "Before refactoring" gorename -diff -offset file.go:#42:5 -to newName # Preview gorename -offset file.go:#42:5 -to newName # Apply go test ./... # Verify ``` ## Working with Modules **Important:** gorename has limitations with Go modules. ### Module-Aware Workaround For module-based projects, consider: 1. Using **gopls rename** instead (recommended) 2. Working with vendored code 3. Using other refactoring tools ```bash # Recommended modern approach gopls rename file.go:42:0 newName ``` ## Integration with Editors ### VS Code 1. Right-click identifier 2. Select "Rename Symbol" or press F2 3. VS Code uses gopls (which has gorename-like functionality) 4. Enter new name 5. Confirm changes ### Vim/Neovim with gopls ```vim " Using LSP client (e.g., coc.nvim, vim-lsp) :call CocActionAsync('rename') " Or with vim-go :GoRename ``` ### Emacs ```elisp ;; Using eglot (eglot-rename ) ;; Or with go-mode (go-rename) ``` ### GoLand/IntelliJ 1. Right-click on identifier 2. Select Refactor > Rename 3. Enter new name 4. Review changes 5. Click Refactor ## Troubleshooting ### "offset: No such file or directory" **Problem:** File path is incorrect or file doesn't exist. **Solution:** ```bash # Use absolute path gorename -offset /full/path/to/file.go:#42:5 -to newName # Verify file exists ls -la /path/to/file.go ``` ### "could not parse offset" **Problem:** Offset format is incorrect. **Solution:** ```bash # Use one of these formats: gorename -offset file.go:#142 # Byte offset gorename -offset file.go:#42:5 # Line:Column # Not: file.go:42:5 (missing # prefix) ``` ### "no packages found" **Problem:** Go build context cannot find packages. **Solution:** ```bash # Ensure you're in a Go project directory pwd ls go.mod # Check go.mod is valid go mod tidy # Try again gorename -offset main.go:#42:5 -to newName ``` ### "Conflict: name XYZ already exists" **Problem:** New name collides with existing identifier. **Solution:** ```bash # Use -diff to see the conflict gorename -diff -offset main.go:#42:5 -to newName # Choose a different name gorename -offset main.go:#42:5 -to differentName # Or use -force (not recommended) gorename -force -offset main.go:#42:5 -to newName ``` ### "identifier not found" **Problem:** Identifier at specified offset not found. **Solution:** ```bash # Verify position with editor # Show context around offset sed -n '40,45p' main.go # Use correct offset gorename -offset main.go:#42:5 -to newName # Consider using gopls instead for easier location ``` ## Best Practices ### 1. Always Preview Large Changes ```bash gorename -diff -offset main.go:#42:5 -to newName | less ``` ### 2. Commit Before Refactoring ```bash git add . git commit -m "Checkpoint: before gorename refactoring" gorename -offset main.go:#42:5 -to newName ``` ### 3. Run Tests After Refactoring ```bash gorename -offset main.go:#42:5 -to newName go test ./... go vet ./... ``` ### 4. Use Version Control to Undo ```bash # If something goes wrong: git checkout . # Or review changes before committing: git status git diff ``` ### 5. Rename Incrementally Don't rename many things at once. Handle one identifier at a time. ```bash # Good: one at a time gorename -offset file1.go:#10:5 -to newName1 gorename -offset file2.go:#20:5 -to newName2 # Avoid: trying to rename multiple at once # (gorename handles one at a time anyway) ``` ### 6. Document Renames in Commit Messages ```bash git commit -m "Refactor: rename calculateTotal to computeTotal - Renamed function for clarity - Updated all 12 call sites - All tests passing" ``` ## Migrating to gopls For new projects or when updating, use gopls instead: ### Command Line ```bash # Modern way (recommended) gopls rename -w file.go:42:0 newName ``` ### Editor Integration Most modern editors automatically use gopls for rename: - VS Code: F2 - Vim/Neovim: LSP rename - Emacs: eglot-rename - GoLand: Refactor > Rename ## Performance Tips 1. **Smaller scope**: Rename within single file/package when possible 2. **During development**: Do refactoring during active development, not at end 3. **Parallel processing**: Let gorename process multiple files 4. **Index cache**: First run may be slower as it builds indexes ## Related Tools | Tool | Purpose | |------|---------| | gopls | Modern rename via LSP (recommended) | | gofmt | Code formatting | | go vet | Code analysis | | go fix | Automatic fixes | | goimports | Auto-import management | ## See Also - [API Reference](API_REFERENCE.md) - [README](README.md) - [gopls Documentation](https://github.com/golang/tools/tree/master/gopls) - [Go Code Review Comments](https://golang.org/doc/effective_go#names)