前置知识
- 至少写过 Java / Python / C 任一语言
- 了解命令行基础(
cd ls export) - 安装过开发工具(JDK / Python / Node.js)
为什么 2018 年学 Go
Go(又称 Golang)由 Google 的 Robert Griesemer、Rob Pike、Ken Thompson 在 2007 年设计,2009 年开源,2012 年发布 1.0。到 2018 年,Go 已经在云原生、DevOps、命令行工具领域成为事实标准:
- Docker(2013-03 开源)—— Go 写的
- Kubernetes(2014-06 开源)—— Go 写的
- Prometheus(2016-05 1.0)—— Go 写的
- etcd / Consul / Terraform —— 都是 Go
Go 1.11 在 2018-08 引入 Go Module(go.mod)——彻底解决 GOPATH 时代的所有依赖管理痛点。本文带你从 0 到 1 搭建 Go 环境,跑通第一个 Hello World。
一、安装 Go
1.1 下载与安装
1
2
3
4
5
| # Windows MSI 安装包(示例:1.19.4)
# https://go.dev/dl/go1.19.4.windows-amd64.msi
# 默认安装路径 <DEV_DIR>go
# 环境变量 Path 自动加 <DEV_DIR>go\bin
|
升级:直接覆盖原安装路径即可。
1.2 验证
1
2
| go version
# go version go1.19.4 windows/amd64
|
1.3 源码获取
1
2
3
| git clone https://go.googlesource.com/go
# 或 GitHub 镜像
git clone https://github.com/golang/go.git
|
二、GOPATH 时代:理解"工作区"概念
2018 年之前,Go 项目必须放在 $GOPATH/src 下才能编译——这与 Java 的 Maven、Python 的 venv、Node 的 npm 都不同。
1
2
3
4
5
6
7
| # 默认 GOPATH
C:\Users\Administrator\go
# go env 关键变量
go env GOPATH
go env GOROOT
go env GOPROXY
|
2.1 早期项目结构
1
2
3
4
5
6
| $HOME/go/
└── src/
└── github.com/
└── yourname/
└── hello/
└── main.go
|
1
2
| mkdir -p $HOME/go/src/github.com/yourname/hello
cd $HOME/go/src/github.com/yourname/hello
|
2.2 Go 1.11 之前的痛点
- 项目必须放
$GOPATH/src 下,否则 import 找不到 - 没有版本概念,
go get 永远拉最新 master - 第三方包版本冲突时只能
git clone 到本地再 replace - 公司内部包上传私有 Git 仓库,每次更新全靠
go get -u
这些痛点催生了 2018 年的 Go Module(1.11 引入,1.14 默认开启)。
三、Go Module 时代(Go 1.11+)
3.1 创建一个 Hello World
1
2
3
4
5
6
| # 任意位置都可(不再强制 $GOPATH/src)
mkdir E:\workspace\go\tutorial\01hello
cd E:\workspace\go\tutorial\01hello
go mod init example/hello
# go: creating new go.mod in module example/hello
|
go.mod 内容:
1
2
3
| module example/hello
go 1.19
|
新建 hello.go:
1
2
3
4
5
6
7
| package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
|
1
2
| go run .
# Hello, World!
|
3.2 导入第三方包
1
2
3
4
5
6
7
8
9
10
| package main
import (
"fmt"
"rsc.io/quote"
)
func main() {
fmt.Println(quote.Go())
}
|
1
2
3
| go mod tidy # 拉取缺失依赖、清理多余
go run .
# Don't communicate by sharing memory, share memory by communicating.
|
go.mod 自动加了一行:
1
| require rsc.io/quote v1.5.2
|
go.sum 记录依赖哈希——保证其他机器拉下来版本一致。
四、Hello 进阶:双模块调用
官方教程 https://go.dev/doc/tutorial/create-module 演示了"两个模块相互调用"的经典场景。
4.1 创建 greetings 模块
1
2
3
| mkdir E:\workspace\go\tutorial\02module\greetings
cd E:\workspace\go\tutorial\02module\greetings
go mod init example.com/greetings
|
greetings.go:
1
2
3
4
5
6
7
8
| package greetings
import "fmt"
func Hello(name string) string {
message := fmt.Sprintf("Hi, %v. Welcome!", name)
return message
}
|
4.2 创建调用方 hello 模块
1
2
3
| mkdir E:\workspace\go\tutorial\02module\hello
cd E:\workspace\go\tutorial\02module\hello
go mod init example.com/hello
|
hello.go:
1
2
3
4
5
6
7
8
9
10
11
| package main
import (
"fmt"
"example.com/greetings"
)
func main() {
message := greetings.Hello("Gladys")
fmt.Println(message)
}
|
4.3 本地 replace
模块未发布,直接 go run . 会报"找不到 example.com/greetings"。
1
2
3
4
5
| # 用本地路径替换远程引用
go mod edit -replace example.com/greetings=../greetings
go mod tidy
go run .
# Hi, Gladys. Welcome!
|
go.mod 会多一行:
1
| replace example.com/greetings => ../greetings
|
发布时把 replace 行删掉,调用方用 go get example.com/greetings@latest 即可。
4.4 错误处理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| package greetings
import (
"errors"
"fmt"
)
func Hello(name string) (string, error) {
if name == "" {
return "", errors.New("empty name")
}
message := fmt.Sprintf("Hi, %v. Welcome!", name)
return message, nil
}
|
调用方:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| package main
import (
"fmt"
"log"
"example.com/greetings"
)
func main() {
log.SetPrefix("greetings: ")
log.SetFlags(0)
message, err := greetings.Hello("")
if err != nil {
log.Fatal(err)
}
fmt.Println(message)
}
|
4.5 随机问候
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| package greetings
import (
"errors"
"fmt"
"math/rand"
)
func Hello(name string) (string, error) {
if name == "" {
return name, errors.New("empty name")
}
message := fmt.Sprintf(randomFormat(), name)
return message, nil
}
func randomFormat() string {
formats := []string{
"Hi, %v. Welcome!",
"Great to see you, %v!",
"Hail, %v! Well met!",
}
return formats[rand.Intn(len(formats))]
}
|
4.6 多人问候
1
2
3
4
5
6
7
8
9
10
11
| func Hellos(names []string) (map[string]string, error) {
messages := make(map[string]string)
for _, name := range names {
message, err := Hello(name)
if err != nil {
return nil, err
}
messages[name] = message
}
return messages, nil
}
|
4.7 单元测试
greetings_test.go:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| package greetings
import (
"regexp"
"testing"
)
func TestHelloName(t *testing.T) {
name := "Gladys"
want := regexp.MustCompile(`\b` + name + `\b`)
msg, err := Hello("Gladys")
if !want.MatchString(msg) || err != nil {
t.Fatalf(`Hello("Gladys") = %q, %v, want match for %#q, nil`, msg, err, want)
}
}
func TestHelloEmpty(t *testing.T) {
msg, err := Hello("")
if msg != "" || err == nil {
t.Fatalf(`Hello("") = %q, %v, want "", error`, msg, err)
}
}
|
4.8 编译安装
1
2
3
4
5
6
7
8
| cd hello
go build
# Windows 下生成 hello.exe
# 配置 GOBIN 后可 go install
go env -w GOBIN=E:\workspace\go\bin
go install
# hello.exe 出现在 GOBIN 目录下
|
五、Go 1.x 历史里程碑
| 版本 | 发布日期 | 关键特性 |
|---|
| 1.0 | 2012-03 | 第一个稳定版 |
| 1.5 | 2015-08 | 编译器自举(用 Go 写 Go 编译器) |
| 1.7 | 2016-08 | context 包、Vendor 目录 |
| 1.11 | 2018-08 | Go Module 引入 |
| 1.13 | 2019-09 | GOPROXY 增强、错误包装 |
| 1.14 | 2020-02 | Module 默认开启 |
| 1.16 | 2021-02 | go install 行为变化(用 @version) |
| 1.18 | 2022-03 | 泛型、模糊测试、Workspace |
| 1.21 | 2023-08 | PGO、log/slog、slices maps cmp 标准库 |
| 1.22 | 2024-02 | for 循环变量行为改变 |
| 1.24 | 2025-02 | 泛型类型别名、Swiss Table map |
六、环境变量核心配置
1
2
3
4
5
6
7
8
9
10
11
| # 关键环境变量
go env GOROOT # Go 安装根目录
go env GOPATH # 工作区(默认 %USERPROFILE%\go)
go env GOMODCACHE # 依赖缓存(C:\Users\Administrator\go\pkg\mod)
go env GOPROXY # 依赖代理
go env GOSUMDB # 校验数据库
go env GOBIN # go install 输出目录
go env GO111MODULE # off / on / auto(1.16+ 默认 on)
go env GOFLAGS # 全局 flags
go env CGO_ENABLED # 是否启用 CGO
go env GOOS / GOARCH # 交叉编译目标
|
6.1 国内代理
1
2
| go env -w GOPROXY=https://goproxy.cn,direct
go env -w GOSUMDB=sum.golang.org
|
七牛、阿里云、字节跳动都提供 GOPROXY 镜像——goproxy.cn 是七牛维护的官方推荐镜像。
6.2 GO111MODULE 三种模式
off:禁用 module,沿用 GOPATH 模式(基本没人用了)on:完全用 module,不去 GOPATH 找auto(默认):当前目录在 GOPATH/src 之外且有 go.mod 才启用 module
Go 1.16 起 auto 默认行为就是 on——新项目务必用 module。
七、IDE 与插件
7.1 IDEA / GoLand
- 装插件 Go、Go Template
- 设置 GOROOT(Go 安装根目录)
- 启用 Go Modules
7.2 VS Code
- 装 Go 扩展(
golang.go)—— 提供 LSP、自动补全、调试 - 推荐
gopls(Go 官方语言服务器)
7.3 快捷键(IDEA)
| 快捷键 | 作用 |
|---|
Alt + Enter | 生成头注释 / 快速修复 |
Ctrl + Shift + T | 选择生成测试 |
八、常见问题
8.1 Delve 调试器版本不匹配
1
| WARNING: undefined behavior - version of Delve is too old for Go version 1.21.0
|
Go 升级了 1.21,但 IDE 还在用老 Delve。解决:
1
2
3
4
| go install github.com/go-delve/delve/cmd/dlv@latest
# 会在 GOPATH/bin 下生成 dlv.exe
# 复制到 IDEA 插件目录
# C:\Users\Administrator\AppData\Roaming\JetBrains\IntelliJIdea2023.1\plugins\go-plugin\lib\dlv\windows\dlv.exe
|
8.2 GOPROXY 拉不到私有仓库
1
2
| go env -w GOPRIVATE=github.com/yourcompany/*
# 私有仓库不走代理、不走 sum 校验
|
九、下一步
- 基础语法:《Go 语言圣经》https://gopl-zh.github.io/
- Web 框架:Gin(轻量)、Echo(极简)、Beego(全栈)
- ORM:GORM(最流行)、XORM、Ent
- 微服务:gRPC-Go、Kitex(字节)、Kratos(哔哩哔哩)
- 云原生:Kubernetes Operator、Client-Go
参考资料
2024+ 视角:Go 1.23 / 1.24 与现代 Go 工程实践
Go 版本演进(2024+ 视角)
| 版本 | 发布时间 | 关键特性 |
|---|
| 1.21 | 2023-08 | PGO、log/slog、标准库 slices / maps / cmp |
| 1.22 | 2024-02 | for 循环变量范围修正、HTTP 路由增强 |
| 1.23 | 2024-08 | iter 包(迭代器协议)、unique 包、structs 标签、maps / slices 增量 |
| 1.24 | 2025-02 | 泛型类型别名、Swiss Table Map 性能 +30%、go.mod toolchain 字段 |
| 1.25(计划) | 2025-08 | 协程本地存储、sync 包增强 |
Go 1.23 必学特性
iter 包 + range-over-func
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| // 1.23 起标准库支持"自定义迭代器"
func Backward[T any](s []T) iter.Seq[T] {
return func(yield func(T) bool) {
for i := len(s) - 1; i >= 0; i-- {
if !yield(s[i]) {
return
}
}
}
}
// 使用(像 Python generator)
for v := range Backward([]int{1, 2, 3}) {
fmt.Println(v) // 3 2 1
}
|
unique 包:值类型化
1
2
3
4
5
6
7
8
| // 替代 map[string]struct{} 做 set,内存省 50%
import "unique"
var once unique.Handle[string]
func intern(s string) string {
return once.Value(s) // 同字符串只存一份
}
|
maps / slices 标准库
1
2
3
4
5
| // 1.21+ 标准库,不再用 golang.org/x/exp
slices.Sort(mySlice)
slices.Reverse(mySlice)
maps.Clone(myMap)
maps.Copy(dst, src)
|
Go 1.24 关键变化
- 泛型类型别名:
type Set[T comparable] = map[T]struct{} 完整支持 - Swiss Table Map:内部 map 性能 +30%,内存占用 -20%
go.mod toolchain 字段:
1
2
3
4
| // go.mod
module my-project
go 1.24
toolchain go1.24.1 // 锁编译工具链
|
PGO(Profile-Guided Optimization)2024+ GA
1
2
3
4
5
6
7
| # 1. 收集 CPU profile
go test -cpuprofile=cpu.prof -bench=.
# 2. 用 profile 编译
go build -pgo=cpu.prof -o myapp .
# 性能提升 5-15%(生产级服务)
|
PGO 在 Go 1.21 起 GA,生产环境强烈建议开——零成本收益。
Go 工具链 2024+ 新范式
go run 简化开发
1
2
3
4
5
| # 跑单个文件(不需要 go.mod)
go run main.go
# 跑远程代码
go run golang.org/x/example/hello@latest
|
go work 多模块开发
1
2
3
4
| # monorepo 多模块
go work init
go work use ./pkg1 ./pkg2
go work edit -replace github.com/me/lib=./lib
|
go test 增强
1
2
3
4
5
6
| # 模糊测试(Fuzzing)
go test -fuzz=FuzzParse -fuzztime=30s
# 代码覆盖率 HTML 报告
go test -coverprofile=cover.out
go tool cover -html=cover.out -o cover.html
|
Go 1.22 的 for 循环"修大坑"
1
2
3
4
5
6
7
8
9
| // 1.22 之前:循环变量共享
for _, v := range []int{1, 2, 3} {
go func() {
fmt.Println(v) // 全部输出 3(v 被覆盖)
}()
}
// 1.22+:每次迭代有独立 v
// 输出 1 2 3(符合直觉)
|
生产意义:闭包捕获循环变量的并发 bug 全部消失。
依赖管理 2024+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| # go.mod 必填字段
module my-project
go 1.24
require (
github.com/gin-gonic/gin v1.10.0
github.com/spf13/viper v1.19.0
)
// 间接依赖
require (
github.com/xx/yy v1.0.0 // indirect
)
// 替换(本地开发)
replace github.com/me/lib => ../lib
// 私有仓库不走 proxy / sum
exclude github.com/me/internal v1.0.0
|
主流 Web 框架 2024+
| 框架 | 定位 | 2024+ |
|---|
| Gin | 主流 HTTP 框架 | 仍是中文社区首选 |
| Echo | 极简高性能 | 性能好 |
| Fiber | Express 风格(基于 fasthttp) | 性能 SOTA |
| Chi | 轻量 + 标准库风格 | 标准项目首选 |
| Hertz | 字节跳动 | 国产高性能 |
| Kratos | B 站 / 微服务 | 复杂业务首选 |
| go-zero | 极客时间 | 国内微服务首选 |
微服务框架对比 2024+
| 框架 | 维护方 | 特点 |
|---|
| go-zero | 好未来 / 万俊峰 | 国内主流 + 自带 goctl 代码生成 |
| Kratos | B 站 | 字节系 + gRPC + 配置中心 |
| Kitex | 字节跳动 | 字节系 + 高性能 RPC |
| Istio + Go | Google | 服务网格 |
| CloudWeGo | 字节跳动 | 字节系全家桶(Hertz + Kitex + Thrift) |
2024+ 实战坑
- go 1.22+
for 循环变量范围修正——老项目升级后并发代码可能行为变化,要全量回归 - PGO 默认开启与否——
go env GOEXPERIMENT 控制 - Swiss Table Map——某些老代码依赖 map 迭代顺序的会有问题
- 泛型类型推断——编译器越来越聪明,但过度嵌套的泛型仍会写得很烂
2024+ 推荐组合
1
2
3
4
5
6
7
8
9
10
11
12
| Go 后端服务(生产)
├── Go 1.24 + toolchain 锁版本
├── go-zero / Kratos(微服务)
├── GORM / SQLx(ORM)
├── go-redis / redigo(Redis)
├── zap / zerolog(日志,slog 标准库)
├── prometheus + Grafana(监控)
├── OpenTelemetry(Tracing)
├── go test + testify(单测)
├── gofuzz(模糊测试)
├── PGO 开启(性能 +5-15%)
└── go.mod 用 BOM(Bill of Materials)管理版本
|