| Tested on | RHEL 10.2 with Go 1.27.0 |
|---|---|
| Package | go 1.27.0 |
| Applies to | Any host with Go installed; Go 1.24+ for tool directive examples |
| Privilege | Normal user |
| Scope | Remove module dependencies from go.mod, undo go get, drop Go 1.24+ tool dependencies, uninstall go install binaries, and clear the module cache. Does not cover vendor workflows or replacing third-party libraries in depth. |
| Related guides | go.mod file not found Getting started with Go Install Go on Ubuntu Import local package without GOPATH Golang declared and not used |
Go does not ship a universal go uninstall command. What you remove depends on how the package entered your environment: a require line in go.mod, a Go 1.24+ tool directive, a standalone binary from go install, or downloaded source sitting in the module cache. The table below maps each case to the command you actually need.
| What you want to remove | Recommended action |
|---|---|
| Project module dependency | Remove imports → go get module@none → go mod tidy |
| Dependency no longer imported | go mod tidy may remove it automatically |
Go 1.24+ tool dependency |
go get -tool package@none → go mod tidy |
CLI installed with go install package@version |
Delete the installed executable |
| Downloaded modules from local cache | go clean -modcache |
The rest of this guide walks through each row with real commands. Run module commands from the directory that contains go.mod.
Remove a dependency from go.mod
A module dependency is a require line (and its transitive graph) in go.mod. Removing it means changing that graph, not deleting folders by hand. I use a small demo module example.com/remove-demo that previously ran go get github.com/gin-gonic/gin@v1.10.0.
Check why the module is required
List every module in the selected graph so you can see whether the one you care about is still present:
go list -m allSample output (trimmed):
example.com/remove-demo
github.com/bytedance/sonic v1.11.6
github.com/bytedance/sonic/loader v0.1.1
github.com/cloudwego/base64x v0.1.4
github.com/cloudwego/iasm v0.2.0
...When the list is long, scroll or filter locally; the important part is confirming the module path and version you plan to drop.
Ask Go why a module is still selected. Use -m so the argument is treated as a module path, not a package path inside that module:
go mod why -m github.com/gin-gonic/ginWith github.com/gin-gonic/gin imported in main.go, the chain names your module and the dependency:
# github.com/gin-gonic/gin
example.com/remove-demo
github.com/gin-gonic/ginIf nothing in your code or tests imports the module, you may instead see (main module does not need module github.com/gin-gonic/gin).
Remove direct imports first
If your source still imports a package from the module, deleting the require line alone does not make the dependency unnecessary. Remove or refactor those imports first. For the demo I replace main.go with a stub that no longer references Gin:
printf 'package main\n\nfunc main() {}\n' > main.goThat edit is what tells the module graph the Gin API is no longer used.
Remove it with go get module@none
Request removal of that module from the selected graph:
go get github.com/gin-gonic/gin@none@none requests removal of that module dependency. Go may also downgrade or remove other modules as needed to maintain a valid module graph. On success it reports what it dropped:
go: removed github.com/gin-gonic/gin v1.10.0Removing one module can downgrade or remove others that depended on it. Do not assume only a single require line changes.
Run go mod tidy
Tidy prunes unused requirements and refreshes go.sum:
go mod tidygo mod tidy exits silently on success when nothing else needs cleanup. Confirm Gin and its former transitive modules are gone:
go list -m allSample output:
example.com/remove-demoOnly the main module remains, which matches a project that no longer pulls Gin into the graph.
When go mod tidy is enough
Readers often ask why they cannot delete the import and run go mod tidy alone. That works when the dependency is no longer required by any package or test in your module. After you remove imports, tidy analyzes the module and drops requirements that nothing references.
Use go get module@none when you intentionally want to remove a specific module and are prepared for Go to adjust other dependencies that require it. If removing imports already made the dependency unnecessary, go mod tidy alone is usually sufficient.
go.mod is plain text and you can edit it by hand, but the go commands understand version constraints and the full graph. Prefer go get and go mod tidy so indirect dependencies and go.sum stay consistent.
Remove a Go tool dependency from go.mod (Go 1.24+)
Go 1.24 added tool directives for development tools tracked in go.mod. Add one with:
go get -tool golang.org/x/tools/cmd/stringer@v0.49.0Go adds a tool line and related require entries. A minimal go.mod can look like this:
module example.com/remove-demo
go 1.27.0
tool golang.org/x/tools/cmd/stringer
require golang.org/x/tools v0.49.0That is different from go install golang.org/x/tools/cmd/stringer@v0.49.0, which places a binary on disk but does not add a tool line to your project's go.mod.
Remove the tracked tool with:
go get -tool golang.org/x/tools/cmd/stringer@noneThe tool line disappears from go.mod, but module requirements that were needed by the tool can remain until you run go mod tidy.
Run tidy to remove requirements that are no longer needed:
go mod tidyAfter tidy, go.mod typically contains only the module and go lines when no other dependencies remain. You run tools in the module with go tool stringer, not by assuming a global install path.
Uninstall a command installed with go install
go install example.com/cmd/tool@v1.2.3 builds an executable. It does not add a project dependency to the current go.mod when you use a version suffix. The binary lands in GOBIN when that variable is set explicitly; otherwise Go uses the bin directory under the first GOPATH entry (normally $HOME/go/bin).
On a default setup, GOBIN is often empty. Check it first:
go env GOBINSample output on a typical user account (blank line means unset):
When GOBIN is empty, ask where Go keeps module downloads and installed tools:
go env GOPATHSample output:
/home/user/goWith no GOBIN, go install places stringer at /home/user/go/bin/stringer. If GOBIN is set, delete from that directory instead.
Install a tool to see the default path when GOBIN is unset:
go install golang.org/x/tools/cmd/stringer@v0.49.0go install finishes quietly; list the binary under GOPATH/bin:
ls -l "$(go env GOPATH)/bin/stringer"Sample output:
-rwxr-xr-x 1 user user 8557462 Aug 23 13:24 /home/user/go/bin/stringerDeleting that file is the uninstall step. Resolve the install directory before rm, because $(go env GOBIN) alone is unsafe when GOBIN is empty (the path collapses to /stringer):
GOBIN=$(go env GOBIN)
if [ -z "$GOBIN" ]; then
GOBIN="$(go env GOPATH)/bin"
fi
rm -f "$GOBIN/stringer"rm -f avoids an interactive prompt in non-interactive shells. Using the same $GOBIN value from above, confirm the binary is gone:
test ! -e "$GOBIN/stringer" && echo "stringer removed"Sample output:
stringer removedGo has no go uninstall subcommand for these installs.
Why the dependency returns after you remove it
A module can reappear after go mod tidy when something in your module still needs it. Common causes:
- Another dependency still requires it (indirect requirement).
- Source or test code still imports it.
- Generated code imports it.
- A
tooldirective still references a package from that module. - Tidy restored it because the graph still requires it for a successful build.
Run the diagnostic again with the module path:
go mod why -m github.com/gin-gonic/ginThe printed chain shows which import path pulled the module back in. For a wider view of edges between modules, go mod graph lists requirement pairs; use it when go mod why points at a long indirect chain.
If a parent library is the only reason the module exists, you must remove or replace that parent, or accept the indirect requirement.
Module cache is not package installation
go clean -modcache deletes downloaded module source from the cache (under $GOPATH/pkg/mod by default). It does not:
- remove
requirelines fromgo.mod; - delete
go installbinaries; - permanently uninstall dependencies from your project.
The next go build or go test can download modules again. Use cache cleanup to reclaim disk space, not to drop a dependency from a project.
Common mistakes
| Mistake | Correct approach |
|---|---|
Searching for go uninstall |
Decide whether it is a module, tool dependency, or installed binary |
| Deleting cache to remove a dependency | Change the module graph with imports, go get @none, or tidy |
Using go get to uninstall a standalone binary |
Delete the executable from GOBIN or GOPATH/bin |
Ignoring empty $GOBIN |
When unset, binaries live in $(go env GOPATH)/bin, not /stringer from $(go env GOBIN)/tool |
Forgetting go mod tidy after go get -tool @none |
Tidy removes require lines that only served the tool |
| Removing a module still imported by code | Remove or refactor imports first |
Using go mod why with a module without -m |
Prefer go mod why -m module/path |
Assuming @none only changes one line |
Graph updates may downgrade or remove other modules |
References
- Go Modules Reference
- Managing dependencies
- go command documentation
- Go 1.24 release notes — tool directives
- Deprecation of go get for installing executables
Summary
Removing a Go package starts with identifying what was added. Module dependencies live in go.mod and leave through import cleanup, go get module@none, and go mod tidy. When you only removed imports and nothing else references the module, go mod tidy alone is often enough.
Go 1.24+ adds a separate case: tool directives tracked with go get -tool, removed with go get -tool package@none and go mod tidy so leftover require lines drop with the tool.
CLI tools from go install package@version are plain files on disk. When GOBIN is empty, they live under GOPATH/bin; when set, under GOBIN. Resolve that path before rm, not $(go env GOBIN)/tool alone. The module cache is yet another layer: go clean -modcache clears downloads but does not edit go.mod.
When a dependency comes back, go mod why -m shows which import path still requires it. Treat that output as the map before you fight tidy or hand-edit go.mod.

