FAQ-17:在 Ubuntu 上安装 Go
预计阅读时间:14 分钟
📖 目录
问题速查表
| 问题 | 解决章节 |
|---|---|
| 安装官方预编译二进制(推荐) | 方式一:安装官方二进制(推荐) |
| 想要最简便的安装方式 | 方式二:使用 Snap |
| 需要从源码编译 Go | 方式三:使用 Git 手动安装(适合开发者) |
| go: command not found | 错误一:go: command not found |
| GOPATH 目录写入权限不足 | 错误二:permission denied 写入 GOPATH |
| GOPATH 是什么?需要配置吗? | 错误三:GOPATH 是什么?需要配置吗? |
| 下载模块超时或缓慢 | 错误四:下载模块超时 |
Go(Golang)是云原生基础设施最常用的语言之一。Docker、Kubernetes、Terraform、Prometheus 等核心项目都用 Go 编写。Go 编译出的是静态链接的单一二进制文件,部署极其方便,非常适合 CLI 工具、微服务和系统级程序的开发。本文提供多种安装方式,并附带完整的环境配置和常见问题排查。
安装方法
方式一:安装官方二进制(推荐)
Go 官方提供了预编译的二进制包,这是最直接、最可控的安装方式。
# 下载最新版本(访问 https://go.dev/dl/ 获取最新版本号)
wget https://go.dev/dl/go1.22.5.linux-amd64.tar.gz
# 解压到 /usr/local(先清理旧版本)
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf go1.22.5.linux-amd64.tar.gz
# 将 Go 加入 PATH(编辑 ~/.bashrc 或 ~/.profile)
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc
echo 'export GOPATH=$HOME/go' >> ~/.bashrc
echo 'export PATH=$PATH:$GOPATH/bin' >> ~/.bashrc
# 重新加载 shell 配置
source ~/.bashrc
# 验证
go version
方式二:使用 Snap
Snap 提供了最简便的安装方式,但版本更新可能稍有滞后。
# 安装 Go
sudo snap install go --classic
# 验证
go version
# 查看安装路径
which go
方式三:使用 Git 手动安装(适合开发者)
如果你需要从源码编译 Go 本身(例如参与 Go 语言开发),可以克隆官方仓库。
# 安装编译依赖
sudo apt install -y git gcc make
# 克隆 Go 源码
git clone https://go.googlesource.com/go
cd go
# 编译(需要已安装的 Go 来编译新版本,称为 bootstrap)
cd src
./make.bash
# 安装编译好的 Go
sudo cp -R ../bin /usr/local/go/bin
sudo cp -R ../pkg /usr/local/go/pkg
# 验证
go version
版本管理
如果你需要在多个 Go 版本之间切换,可以使用 gvm(Go Version Manager)或手动管理。
# 查看当前安装的 Go 版本
go version
# 下载新版本(覆盖安装)
# 访问 https://go.dev/dl/ 获取版本号
wget https://go.dev/dl/go1.21.13.linux-amd64.tar.gz
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf go1.21.13.linux-amd64.tar.gz
# 使用 gvm 管理多版本(可选)
bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)
gvm install go1.22.5
gvm use go1.22.5 --default
在 Go 项目中,可以通过 go.mod 文件的 go 指令声明所需的最低 Go 版本,确保团队成员使用一致的版本。
Go 环境验证
安装后先执行 go env 确认关键配置,常见的环境问题大多集中在这几个字段:
$ go env
GOROOT=/usr/local/go # Go 安装目录(官方二进制默认)
GOPATH=/root/go # 工作区:源码/缓存/编译产物
GOBIN= # 空=go install 产物放到 $GOPATH/bin
GOPROXY=https://proxy.golang.org,direct # 模块下载源
GO111MODULE=on # 模块模式(1.16+ 默认开启)
# 快速自检三步
go version # 版本
go env GOPATH # 工作区路径
go install golang.org/x/tools/gopls@latest # 装一个工具验证 go install 可用
GOPATH vs Go Modules:Go 1.11+ 引入模块模式后,项目不再强制放在 $GOPATH/src 下,任何目录都可以建 go.mod 独立开发。若发现"import 报 cannot find package",多半是模块模式未开启(GO111MODULE=off)或依赖未下载(go mod tidy)。
GOPROXY 配置:国内网络推荐使用镜像加速,避免下载超时:
go env -w GOPROXY=https://goproxy.cn,direct
go env -w GOSUMDB=sum.golang.org # 保持校验和验证
常见错误
错误一:go: command not found
Go 的可执行文件不在系统 PATH 中。确认 /usr/local/go/bin 已加入 PATH:
# 检查 PATH
echo $PATH | tr ':' '\n' | grep go
# 如果没有,手动添加
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc
source ~/.bashrc
# 验证
go version
错误二:permission denied 写入 GOPATH
Go 在下载模块和编译时需要写入 $GOPATH(默认为 ~/go)。如果该目录权限有问题:
# 确认 GOPATH 目录存在且可写
ls -la ~/go
mkdir -p ~/go
chmod -R u+w ~/go
错误三:GOPATH 是什么?需要配置吗?
Go 模块在 1.16+ 版本后已不需要设置 GOPATH 来存放项目代码。模块代码可以存放在任意目录,使用 go mod init 初始化即可。GOPATH 现在主要用于存放下载的模块缓存和编译产物。
# 查看 Go 环境配置
go env GOPATH GOROOT GOMODCACHE
# 清理模块缓存(磁盘空间不足时有用)
go clean -modcache
错误四:下载模块超时
国内网络环境下,Go 模块代理可能连接缓慢:
# 设置国内镜像代理
go env -w GOPROXY=https://goproxy.cn,direct
# 验证设置
go env GOPROXY
# 如果需要绕过代理
go env -w GOPROXY=off
错误五:go vet 或编译报错——缺少 C 编译器
某些 CGO 包(如 sqlite3)需要 C 编译器:
# 安装 gcc 和相关工具
sudo apt install -y gcc libc6-dev
# 禁用 CGO 编译纯 Go 项目(可选)
CGO_ENABLED=0 go build -o myapp
真实案例
案例 A:go install 装好的工具命令找不到
用户执行 go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest 成功,但运行 golangci-lint 却提示 command not found。
# 报错
golangci-lint: command not found
# 排查:go install 的产物在哪
go env GOBIN # 为空
go env GOPATH # /root/go
# 产物实际在 $GOPATH/bin(GOBIN 为空时的默认位置)
ls /root/go/bin/ # golangci-lint 存在
# 修复:把 GOBIN 加入 PATH
echo 'export PATH=$PATH:$(go env GOPATH)/bin' >> ~/.bashrc
source ~/.bashrc
# 验证
which golangci-lint
根因:GOBIN 未设置时工具装到 $GOPATH/bin,而该目录不在 PATH;验证:which golangci-lint 输出实际路径,新开终端也正常。
案例 B:GO111MODULE 旧项目 import 报错
# 报错
cannot find package "github.com/gin-gonic/gin" in any of:
/usr/local/go/src/github.com/gin-gonic/gin (from $GOROOT)
/root/go/src/github.com/gin-gonic/gin (from $GOPATH)
# 排查:项目没有 go.mod(还是 GOPATH 时代的项目)
ls go.mod # No such file
# 修复:初始化模块并拉取依赖
go mod init myapp
go get github.com/gin-gonic/gin
go mod tidy
# 验证
go build ./... # 编译通过
根因:项目停留在 GOPATH 模式(GO111MODULE=off 或无 go.mod);修复:go mod init 迁移到模块模式;验证:go build 成功,go.mod 已生成并记录依赖版本。
案例 C:GOPROXY 未设置导致国内环境依赖下载超时
现象:执行 go get github.com/gin-gonic/gin 卡住很久后报 dial tcp: lookup proxy.golang.org: no such host。
# 默认代理 proxy.golang.org 在国内不可达
$ go env GOPROXY
https://proxy.golang.org,direct
# 设置国内代理
$ go env -w GOPROXY=https://goproxy.cn,direct
$ go env GOPROXY
https://goproxy.cn,direct
# 重新拉取依赖
$ go get github.com/gin-gonic/gin # 秒级完成
根因:Go 模块默认通过 proxy.golang.org 下载依赖,该服务在国内访问不稳定。
修复:go env -w GOPROXY=https://goproxy.cn,direct 设置国内镜像代理。direct 表示代理不存在时直接从源站下载。
验证安装
# 查看版本
go version
# 查看环境配置
go env
# 创建测试项目
mkdir ~/hello && cd ~/hello
go mod init hello
# 创建 main.go
cat > main.go << 'GOEOF'
package main
import "fmt"
func main() {
fmt.Println("Hello from Go!")
}
GOEOF
# 编译并运行
go run main.go
# 编译为独立二进制文件
go build -o hello ./main.go
./hello
# 交叉编译(编译为 ARM64 架构)
GOOS=linux GOARCH=arm64 go build -o hello-arm64 ./main.go
# 清理
rm -f hello hello-arm64
cd ~ && rm -rf ~/hello
案例 D:go build 报 no required module provides package
项目依赖一个内部包,执行 go build 报 no required module provides package。
# 报错
no required module provides package mycompany.com/internal/pkg:
mycompany.com/internal/pkg imported by myapp
to add it: go get mycompany.com/internal/pkg
# 排查:go.mod 中没有声明该依赖
cat go.mod | grep mycompany
# 无输出
# 修复:添加私有仓库配置
go env -w GOPRIVATE=mycompany.com/*
go env -w GONOSUMDB=mycompany.com/*
go env -w GONOPROXY=mycompany.com/*
# 配置 git 凭证(私有仓库需要认证)
git config --global url."git@github.com:mycompany/".insteadOf "https://github.com/mycompany/"
# 拉取依赖
go get mycompany.com/internal/pkg
go mod tidy
# 验证
go build ./...
根因:Go 模块默认通过公共代理下载,私有仓库需要配置 GOPRIVATE 和认证方式;修复:设置 GOPRIVATE 跳过代理和校验,并配置 Git 凭证;预防:团队文档中记录私有仓库配置步骤。
案例 E:交叉编译报 CGO_ENABLED=1 错误
执行 GOOS=linux GOARCH=arm64 go build 报错找不到 C 编译器,原因是启用了 CGO 但缺少目标架构的交叉编译工具链。
# 报错(真实输出:找不到目标架构的 C 交叉编译器)
$ CGO_ENABLED=1 GOOS=linux GOARCH=arm64 go build -o myapp
# exec: "aarch64-linux-gnu-gcc": executable file not found in $PATH
# 原因:CGO_ENABLED=1 时需要目标架构的 C 交叉编译器
# 解决方案一:禁用 CGO(纯 Go 项目推荐)
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o myapp-arm64
# 解决方案二:安装交叉编译工具链
sudo apt install -y gcc-aarch64-linux-gnu
CC=aarch64-linux-gnu-gcc CGO_ENABLED=1 GOOS=linux GOARCH=arm64 go build -o myapp-arm64
# 解决方案三:使用 Docker 交叉编译
docker run --rm -v "$PWD":/work -w /work golang:1.22 \
GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build -o myapp-arm64 .
# 验证
file myapp-arm64 # ELF 64-bit LSB executable, ARM aarch64
根因:CGO 启用时 Go 需要调用 C 编译器,交叉编译需要对应架构的交叉编译器;修复:纯 Go 项目禁用 CGO(CGO_ENABLED=0),需要 CGO 则安装交叉编译工具链。
版本管理详解
gvm 完整使用指南
gvm(Go Version Manager)是 Go 的多版本管理工具,类似于 nvm 之于 Node.js:
# 安装 gvm
bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)
# 重新加载 shell
source ~/.bashrc
# 查看已安装版本
gvm list
# gvm
# go1.21.13
# go1.22.5
# => go1.22.6
# stable
# 安装指定版本
gvm install go1.22.6
gvm install go1.21.13
# 切换版本
gvm use go1.21.13
gvm use go1.22.6 --default # 设为默认
# 使用 stable 通道自动安装最新稳定版
gvm install stable
gvm use stable --default
# 卸载版本
gvm uninstall go1.21.13
# 查看远程可用版本
gvm listall | grep "1.22"
# 注意:gvm 会覆盖 GOROOT,切换版本后检查环境
go env GOROOT
go version
手动管理多版本
如果不想安装额外工具,可以手动管理多个 Go 版本:
# 下载多个版本
wget https://go.dev/dl/go1.21.13.linux-amd64.tar.gz
wget https://go.dev/dl/go1.22.6.linux-amd64.tar.gz
# 解压到不同目录
sudo tar -C /usr/local -xzf go1.21.13.linux-amd64.tar.gz
sudo mv /usr/local/go /usr/local/go1.21.13
sudo tar -C /usr/local -xzf go1.22.6.linux-amd64.tar.gz
sudo mv /usr/local/go /usr/local/go1.22.6
# 创建切换脚本
cat > ~/go-switch.sh << 'EOF'
#!/bin/bash
VERSION=${1:-"1.22.6"}
sudo rm -rf /usr/local/go
sudo ln -s /usr/local/go${VERSION} /usr/local/go
go version
EOF
chmod +x ~/go-switch.sh
# 使用
~/go-switch.sh 1.21.13 # 切到 1.21.13
~/go-switch.sh 1.22.6 # 切到 1.22.6
go.mod 中的版本约束
# go.mod 中声明最低 Go 版本
module myapp
go 1.21 # 最低要求 Go 1.21
# go.sum 校验和(提交到 Git,确保依赖完整性)
# go.sum 由 go mod tidy 生成,不要手动修改
# 查看模块可用版本
go list -m -versions github.com/gin-gonic/gin
# github.com/gin-gonic/gin v1.7.0 v1.7.1 ... v1.9.1
# 升级依赖到最新版
go get -u github.com/gin-gonic/gin@latest
# 升级所有直接依赖
go get -u
# 降级依赖
go get github.com/gin-gonic/gin@v1.9.0
# 查看可升级的依赖
go list -m -u all
# tidy:清理不需要的依赖,添加缺少的依赖
go mod tidy
# vendor:将依赖复制到 vendor 目录(离线构建)
go mod vendor
go build -mod=vendor ./...
GOPROXY 镜像对比
# 国内常用镜像
go env -w GOPROXY=https://goproxy.cn,direct # 七牛云(推荐)
go env -w GOPROXY=https://goproxy.io,direct # goproxy.io
go env -w GOPROXY=https://mirrors.aliyun.com/goproxy # 阿里云
# 自建代理(企业内网)
# 使用 go module 镜像工具:goproxy
go install github.com/goproxyio/goproxy@latest
goproxy -listen=:8080 -cache-dir=/tmp/goproxy-cache
# 各代理特点
# goproxy.cn: 国内最稳定,七牛云维护,同步速度快
# goproxy.io: 国际版,国内可用但速度略慢
# 阿里云镜像: 需要阿里云内网访问权限
故障排查决策树
当 Go 环境出现问题时,按以下流程排查:
问题:go: command not found
├── which go 有输出?
│ ├── 是 → PATH 正常,检查是否被覆盖:type go
│ └── 否 → 查找安装位置:
│ ├── ls /usr/local/go/bin/go /snap/bin/go 2>/dev/null
│ │ ├── 有 → 加入 PATH
│ │ └── 无 → 未安装:选择安装方式
│ └── gvm 环境?
│ ├── gvm list 查看已安装版本
│ ├── gvm use 激活
│ └── source ~/.bashrc 重新加载 gvm 初始化
问题:go build 报 "cannot find package"
├── 检查模块模式:go env GO111MODULE
│ ├── off → 设置开启:go env -w GO111MODULE=on
│ └── on → 继续排查
├── 检查 go.mod 是否存在
│ ├── 不存在 → 初始化:go mod init myapp
│ └── 存在 → 继续排查
├── 检查依赖是否下载:go mod download
│ ├── 失败 → 检查 GOPROXY:go env GOPROXY
│ │ └── 设置国内代理:go env -w GOPROXY=https://goproxy.cn,direct
│ └── 成功 → 检查包名拼写和版本
问题:go install 工具命令找不到
├── 检查 GOBIN:go env GOBIN
│ ├── 为空 → 工具在 $(go env GOPATH)/bin
│ ├── 有值 → 工具在 $GOBIN
│ └── 修复:echo 'export PATH=$PATH:$(go env GOPATH)/bin' >> ~/.bashrc
└── 验证:which
问题:go mod tidy 报错
├── 检查网络:go env GOPROXY
│ └── 设置代理:go env -w GOPROXY=https://goproxy.cn,direct
├── 检查 go.mod 语法:cat go.mod
│ └── 修复语法错误(缺少 module 声明等)
└── 检查版本约束冲突
└── 调整 go.mod 中的 require 版本
问题:交叉编译报错
├── CGO_ENABLED=1 时缺少交叉编译器
│ └── 禁用 CGO:CGO_ENABLED=0 go build
├── 目标平台不支持
│ └── 检查 GOOS/GOARCH 组合是否有效
└── Docker 交叉编译
└── 使用官方 golang 镜像构建
生产环境配置建议
- 使用 Go Modules 锁定依赖:所有项目都应使用
go.mod和go.sum,CI 中用go mod verify校验依赖完整性。 - 设置国内镜像代理:生产环境部署时配置
GOPROXY=https://goproxy.cn,direct,加速构建过程。 - 使用多阶段 Docker 构建:builder 阶段编译,runtime 阶段只复制二进制文件,镜像体积可从 800MB+ 降到 10MB 以下。
- 启用 go vet 和 staticcheck:CI 中加入
go vet ./...和staticcheck ./...作为代码质量卡点。 - 使用 race detector 检测并发问题:测试时开启
go test -race ./...,检测数据竞争。 - 保持 Go 版本更新:Go 小版本更新通常包含安全修复,建议至少保持在最新两个小版本。生产环境可锁定版本:
go env -w GOVERSION=go1.22.6。 - 善用交叉编译准备部署:在开发机上交叉编译出 ARM64 二进制,直接部署到 ARM 服务器,无需在目标机器上安装 Go 环境。
- 使用 go generate 管理代码生成:在代码中用
//go:generate注释声明需要生成的代码,统一代码生成流程。
案例 F:go mod tidy 报 "go.sum has unexpected contents"
执行 go mod tidy 报错 go.sum has unexpected contents,怀疑 go.sum 被篡改。
# 报错
go: go.sum has unexpected contents
go: updates to go.sum needed
# 排查:go.sum 文件内容异常
head -5 go.sum
# 内容看起来正常
# 可能原因:go.sum 与 go.mod 不同步
# (有人手动修改了 go.mod 但没更新 go.sum)
# 修复:删除 go.sum 重新生成
rm go.sum
go mod tidy
# 或直接更新
go mod download all
# 验证
go mod verify # 校验通过
go build ./... # 编译通过
根因:go.sum 与 go.mod 不同步(可能是手动编辑或分支合并冲突导致);修复:删除 go.sum 后执行 go mod tidy 重新生成。
案例 G:32 位系统无法运行 64 位 Go 程序
在 32 位系统上运行 64 位交叉编译出的测试/二进制,报 exec format error。
# 报错(真实输出:架构不匹配,内核拒绝加载)
bash: ./myapp: cannot execute binary file: Exec format error
# 排查:检查系统架构
uname -m # i686(32位)
# 原因:Go 1.22 起官方不再提供 32 位安装包(amd64 二进制无法在 i386 上运行)
# 修复:改用 64 位系统编译/运行,或在 64 位机器上交叉编译
GOOS=linux GOARCH=amd64 go build -o myapp ./...
# 或安装 64 位 Go(如果系统支持)
wget https://go.dev/dl/go1.22.6.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.22.6.linux-amd64.tar.gz
# 验证
go env GOARCH # amd64
根因:Go 1.21+ 不再支持 32 位架构,在 32 位系统上运行测试需要交叉编译为 64 位;修复:设置 GOARCH=amd64 交叉编译。
最佳实践
- 使用 Go Modules:所有 Go 项目都应使用模块管理依赖,在项目根目录运行
go mod init初始化。 - 设置国内镜像代理:在国内网络环境下,配置
GOPROXY=https://goproxy.cn,direct可以显著加速依赖下载。 - 使用 go vet 检查代码:在提交代码前运行
go vet ./...检查潜在错误,比编译器更严格。 - 保持 Go 版本更新:Go 的小版本更新通常包含安全修复和性能改进,建议至少保持在最新的两个小版本。
- 善用交叉编译:Go 的交叉编译非常方便,可以在 x86 机器上编译出 ARM64 二进制,适合为不同架构的服务器准备部署文件。
延伸阅读
- 1.8:软件包管理 软件包管理——手动安装 vs 包管理器
- 5.2:Docker 生产实践 Docker 容器化部署生产实践——多阶段构建 Go 应用
案例 H:go workspace 模式与模块模式冲突
现象:在 monorepo 项目中执行 go build ./... 报错 no required module provides package,但依赖已下载:
# 报错
no required module provides package mycompany.com/internal/pkg:
mycompany.com/internal/pkg imported by myapp
to add it: go get mycompany.com/internal/pkg
# 检查 go.work 文件
$ cat go.work
go 1.22
use (
./app1
./app2
)
排查过程:
# 检查 go.work 模式是否启用
$ go env GOWORK
auto
# 尝试关闭 workspace 模式
$ GOWORK=off go build ./...
# 成功
根因:go.work 文件中 use 的模块路径与实际目录结构不匹配,导致 workspace 模式下依赖解析失败。
修复:
# 修正 go.work 中的模块路径
cat > go.work << 'EOF'
go 1.22
use (
./app1
./app2
./shared
)
EOF
# 同步依赖
go work sync
# 验证
go build ./...
预防:使用 go workspace 前确保所有模块路径正确。团队协作时将 go.work 提交到 Git,确保所有人使用相同的 workspace 配置。