一,Go语言介绍
Go语言(又称Golang)是由Google开发的一种静态类型、编译型的开源编程语言,诞生于2009年,并于2012年发布正式稳定版本。其设计团队由三位计算机科学领域的先驱组成:Robert Griesemer、Rob Pike和Ken Thompson(后者是Unix和C语言的共同创始人)。Go语言的设计目标是解决现代软件开发中的痛点,如代码复杂性、编译速度慢、并发编程困难以及跨平台支持不足等问题。
1.1 核心设计理念
-
简洁高效 Go语法类似C语言,但通过去冗余设计简化代码结构。例如:
- 移除类继承、构造函数、注解等复杂概念。
- 不支持函数重载和运算符重载。
- 强制代码格式化工具
gofmt
统一代码风格,减少风格争议。
-
原生并发支持 Go的并发模型基于CSP理论(Communicating Sequential Processes),核心机制为:
- Goroutine:轻量级线程,由Go运行时管理,创建成本极低(初始仅2KB栈,动态扩展)。
- Channel:类型安全的管道,用于Goroutine间通信,避免共享内存导致的竞态问题。
func main() { ch := make(chan int) go func() { ch <- 42 }() // 启动Goroutine发送数据 fmt.Println(<-ch) // 接收数据 }
-
内存管理 Go内置自动垃圾回收(GC),通过三色标记清除算法优化延迟,现代版本(如Go 1.14+)的GC停顿时间通常低于1毫秒。
1.2 语言特性
-
类型系统
-
静态类型:编译时检查类型错误,提升代码健壮性。
-
接口隐式实现:类型无需显式声明实现接口,只需定义相同方法即可。
-
泛型支持:Go 1.18引入泛型,通过
类型参数
增强代码复用性。func Swap[T any](a, b T) (T, T) { return b, a }
-
-
错误处理 采用显式错误返回而非异常机制,鼓励开发者主动处理错误:
file, err := os.Open("file.txt") if err != nil { log.Fatal(err) } defer file.Close() // 确保资源释放
-
工具链
- 跨平台编译:通过
GOOS
和GOARCH
环境变量生成不同平台的二进制文件。 - 依赖管理:Go Modules支持版本化依赖管理,替代旧版GOPATH模式。
- 测试与性能分析:内置
go test
框架和pprof
性能分析工具。
- 跨平台编译:通过
1.3 标准库与生态系统
- 丰富的标准库
- 网络服务:
net/http
库支持快速构建HTTP服务器(如默认实现每秒可处理数万请求)。 - 加密与编码:提供AES、RSA、JSON、XML等标准支持。
- 并发原语:
sync
包提供互斥锁、条件变量等。
- 网络服务:
- 活跃的第三方生态
- Web框架:Gin、Echo、Fiber等高性能框架。
- 微服务与云原生:Kubernetes、Docker、Etcd等核心项目均用Go编写。
- 数据库驱动:支持PostgreSQL、MySQL、MongoDB等主流数据库。
1.4 适用场景
- 后端服务与微服务 Go的高并发和低内存占用特性使其适合构建API网关、分布式系统等。
- 云计算与DevOps工具 如Kubernetes、Prometheus、Terraform等基础设施项目依赖Go的高效编译和部署能力。
- 命令行工具 单二进制文件分发(无外部依赖)特性适合开发CLI工具,如GitHub CLI、Cobra框架应用。
1.5 优缺点
优势
- 编译速度快(大型项目通常在数秒内完成)。
- 部署简单,生成静态二进制文件。
- 并发模型简化多线程编程。
局限
- 泛型支持较晚,旧代码可能缺乏通用性。
- 错误处理代码可能显冗长。
- 不适合实时系统(因GC存在不确定延迟)。
二,Go的安装与配置
2.1 语言环境安装
由于Go语言官网下载速度比较慢,这里推荐大家使用Go语言中文网下载即可,而且Go语言官网和这个中文网发版基本同步。
点击下载后,会在下载文件夹中出现上面选择的文件,由于文件属于安装包,还是需要解压安装的,这里直接双击即可呈现下图,然后选择Next:
一直选择下一步,最后安装完成后应该呈现如下图:
2.2 环境验证
先Win + R
唤醒运行窗口之后,输入cmd
打开控制台窗口,输入go version
,可查看安装的go版本,检查其是否安装成功。
在高版本里安装时会默认在环境变量中配置。
2.3 配置代理
在使用Go进行开发时,可能我们需要借用Go下载一些包什么的,但是默认官网源在国内访问不到,默认官网源如下
https://proxy.golang.org,direct
因此,我们需要配置GOPROXY(代理)。在控制台输入go env
,可查看go的初始环境配置,然后执行以下命令,进行修改代理,将其替换成国内镜像源。Windows 下设置 GOPROXY 的命令为:
go env -w GOPROXY=https://goproxy.cn,direct
重新执行go env
查看Go配置,结果如下图:
2.4 配置包目录说明
首先在终端里输入go env
命令可查看go相关环境变量,会发现GOPATH为用户家目录。
点进去这个家目录下的go文件夹里,我们会发现里面有两个包文件:
这两个包目录
名称 | 作用 |
---|---|
pkg目录 | 常用于缓存第三方包文件 |
bin目录 | 常用于存放可执行文件:通过go install 命令下载的第三方包会放到$GOPATH/go 下面的缓存目录,编译好的可执行文件会放到$GOPATH/go/bin 下 |
然后继续点进去bin目录里,我们会发现3个基本的可执行文件
这三个文件
文件名 | 作用 | 安装命令 |
---|---|---|
dlv | go-delve是Go语言的调试利器 | go install -v github.com/go-delve/delve/cmd/dlv@latest |
gopls | 官方提供的实现语言服务器协议LSP的Language Server,具有构建、格式化、自动完成等功能。 | go install -v golang.org/x/tools/gopls@latest |
staticcheck | 静态代码检查作用 | go install -v honnef.co/go/tools/cmd/staticcheck@latest |
最后对安装包的两个命令也做个总结:
名称 | 作用 |
---|---|
go install命令 | 下载的第三方包会放到$GOPATH/go 下面的缓存目录,编译好的可执行文件会放到$GOPATH/go/bin 下 |
go get命令 | 下载第三方包会放到$GOPATH/go 下面的缓存目录,但不会编译,只是为了后面编程用到这些包 |
2.5 环境变量
查看 go 的环境变量的命令为go env
:
上面打印出来的环境变量有很多,但着重理解并记住这几个环境变量的定义即可:
变量名 | 解释 |
---|---|
GOPATH | go 的工作目录 |
GOROOT | go 的安装目录 |
GOBIN | go 的bin文件目录 |
GO111MODULE | go mod 开关 on为开启go mod |
GOPROXY | 设置代理来加速模块下载 |
2.5.1 GOPATH
GOPATH 是 Go语言中使用的一个环境变量,它使用绝对路径提供项目的工作目录。GOPATH是早期的设置方式,将工作目录设置 GOPATH 到全局环境变量。不同的项目都在 GOPATH/src/
下。
很显然这种设置方法是不太方便的,因为不同项目引用的 package 到放到了一起,这用 Git管理起来很麻烦。
- 比如我们有这样一个场景:A项目引用了 a和b 两个 package,B 项目引用了 c和d 两个 package,那么如果我在 A 中修改了 package 的内容,我提交A项目时想要带着 package 时就很麻烦。
- 其次是 如果Go语言所依赖的所有的第三方库都放在 GOPATH 这个目录下面,这就导致了同一个库只能保存一个版本的代码。如果不同的项目依赖同一个第三方的库的不同版本,应该怎么解决?
2.5.2 GO Module
那么为了解决上述问题,官方从从Go语言1.11 版本之后推出了版本管理工具go module
,并且从 Go语言1.13 版本开始,go module
成为了Go语言默认的依赖管理工具。
在Go语言 1.12 版本之前,要启用go module
工具首先要设置环境变量 GO111MODULE
,不过在Go语言 1.13 及以后的版本则不再需要设置环境变量。
通过 GO111MODULE
可以开启或关闭 go module 工具。
GO111MODULE=off
禁用 go module,编译时会从 GOPATH 和 vendor 文件夹中查找包;
GO111MODULE=on
启用 go module,编译时会忽略 GOPATH 和 vendor 文件夹,只根据 go.mod下载依赖;
GO111MODULE=auto
(默认值),当项目在 GOPATH/src 目录之外,并且项目根目录有 go.mod 文件时,开启 go module。
Windows 下开启 GO111MODULE 的命令为:
set GO111MODULE=on 或者 set GO111MODULE=auto
注意:现在新版本Go语言在配置环境变量时,只需要设置GOPROXY替换一下代理,无需再额外配置GOROOT、GOPATH。
2.5.3 修改GoPath
默认情况下GOPATH是安装到C盘下面的,而这个目录是用来存储一些package的,C盘空间有限,故不希望存C盘,这个时候就需要修改了,只需要在环境变量里面设置修改即可,如图所示
2.6 版本管理
2.6.1 vendor
Go 语言中的 vendor
目录是一种用于项目级依赖隔离的机制,其核心目标是在项目中嵌入依赖的副本,以实现 离线构建 和 版本锁定。
-
什么是
vendor
目录?-
定义:
vendor
是 Go 项目中的一个特殊目录(通常位于项目根目录),用于存储项目依赖的完整副本。 -
历史背景:在 Go Modules 出现之前,社区工具(如
dep
、glide
)通过vendor
管理依赖。Go 1.5+ 开始原生支持vendor
,但 Go Modules 推出后其重要性下降。 -
文件结构:
my-project/ ├── go.mod ├── go.sum ├── main.go └── vendor/ ├── github.com/ │ └── gin-gonic/ │ └── gin/ # 依赖的完整代码 └── modules.txt # 依赖列表及版本
-
-
vendor
的作用离线构建
-
场景:当无法访问互联网(如内网环境)时,直接使用
vendor
内的依赖副本构建项目。 -
命令:
go build -mod=vendor # 强制使用 vendor 目录构建
版本锁定
- 避免意外升级:将依赖代码固化在
vendor
中,防止因外部仓库修改或删除导致构建失败。 - 一致性保障:确保团队成员或 CI/CD 环境使用完全相同的依赖版本。
依赖审计
- 透明化依赖代码:直接查看
vendor
中的代码,便于安全审查或调试。
-
-
生成
vendor
目录使用 Go Modules 生成:在项目根目录运行以下命令,自动将
go.mod
中的依赖复制到vendor
:go mod vendor # 根据 go.mod/go.sum 生成 vendor 目录
生成的
vendor/modules.txt
会记录依赖的精确版本。 -
4.
vendor
vs Go Modules特性 vendor
目录Go Modules 依赖存储位置 项目内的 vendor
目录全局缓存 ( $GOPATH/pkg/mod
)版本控制 代码副本固化在项目中 通过 go.mod
和go.sum
声明版本网络依赖 无需网络(离线构建) 首次构建需下载依赖 项目体积 较大(包含依赖代码) 较小(仅记录版本信息) 维护成本 需手动更新或定期执行 go mod vendor
全自动管理
2.6.2 go.sum
定义:go.sum
:依赖内容的“指纹”校验文件(自动生成,禁止手动修改)
作用:定义 Go 模块的元数据和依赖声明。
内容:
- 模块名称(
module example.com/my-project
)。 - Go 版本要求(
go 1.21
)。 - 直接依赖列表(
require github.com/foo/bar v1.2.3
)。 - 依赖替换规则(
replace
或exclude
)。
示例:
module example.com/app
go 1.21
require (
github.com/gin-gonic/gin v1.9.1
golang.org/x/sys v0.12.0 // indirect
)
replace github.com/old/pkg => ../local/pkg
2.6.3 go.mod
定义:依赖版本的管理清单(开发者直接编辑或通过 go get
管理)
作用:记录依赖的加密哈希值,确保依赖内容的完整性。
内容:
- 每行格式:
模块名 版本 哈希值
。 - 包含直接依赖和间接依赖的哈希值。
示例:
github.com/gin-gonic/gin v1.9.1 h1:4+fr4g88Y5f+8cF7aY0q7ZtVd+kd8i6A/5E5K7x1m0=
github.com/gin-gonic/gin v1.9.1/go.mod h256:xyz...
go.mod
:依赖版本的管理清单(开发者直接编辑或通过 go get
管理)。
2.6.4 和Maven对比
太难理解了,直接和Maven进行对比
核心类比
Go Modules | Maven | 相似点 |
---|---|---|
go.mod | pom.xml | 声明项目元数据与依赖版本 |
go.sum | 依赖的 .sha1 校验文件 | 确保依赖完整性 |
go get / go mod tidy | mvn dependency:resolve | 依赖解析与下载 |
依赖来源
- Go Modules:
- 去中心化:依赖直接从代码仓库(如 GitHub)下载,无需中央仓库(但支持代理镜像如
GOPROXY
)。 - 语义化版本(SemVer):版本号显式包含在模块路径中(如
github.com/foo/bar/v2
)。
- 去中心化:依赖直接从代码仓库(如 GitHub)下载,无需中央仓库(但支持代理镜像如
- Maven:
- 中央仓库:依赖默认从 Maven Central 或 Nexus 等仓库下载。
- 坐标定位:依赖通过
groupId
、artifactId
、version
定位。
依赖锁定
- Go:
go.mod
声明最低兼容版本,实际构建时使用满足约束的最新版本(通过 MVS 算法解析)。go.sum
记录所有依赖的哈希值,确保内容一致性。
- Maven:
pom.xml
中版本固定(除非使用范围版本如[1.0,2.0)
)。- 通过
mvn dependency:purge-local-repository
清理本地缓存。
构建与生命周期
- Go:
- 无内置构建生命周期(如
clean
、compile
、package
),需借助 Makefile 或脚本。 - 编译为静态二进制文件,无
target
目录概念。
- 无内置构建生命周期(如
- Maven:
- 强绑定构建生命周期(
compile
→test
→package
等)。 - 输出产物为
jar
/war
,存储在target
目录。
- 强绑定构建生命周期(
操作命令对比
功能 | Go 命令 | Maven 命令 |
---|---|---|
初始化项目 | go mod init <module-name> | mvn archetype:generate |
添加依赖 | go get github.com/foo/bar@v1.2 | 编辑 pom.xml + mvn install |
更新依赖 | go get -u | 修改版本号 + mvn update |
清理缓存 | go clean -modcache | mvn dependency:purge-local-repository |
总结
go.mod
≈pom.xml
: 二者均为依赖管理的核心配置文件,但 Go 的版本解析更动态,Maven 更静态。go.sum
≠pom.xml
:go.sum
更接近 Maven 依赖的校验文件(如.sha1
),但设计上更严格(强制记录所有依赖哈希)。- 哲学差异: Go 强调极简主义(无构建生命周期、去中心化依赖),而 Maven 提供全功能构建框架(插件化、中央仓库)。
三,编写程序
package main
import "fmt"
func main() {
// 打印 helloworld
fmt.Println("Hello World")
}
Go程序语法的用法解释:
- 第1行: 它包含程序的主体程序包,具有程序的整体内容。这是运行程序的起点,因此必须编写程序。
- 第2行: 它包含import“ fmt”,这是一个预处理程序命令,它告诉编译器包括位于程序包中的文件。
- 第三行: 主函数,它是程序执行的开始。
- 第4行: fmt.Println()是一个标准的库函数来打印的东西作为一个screen.In输出此,fmt包已经transmited的println方法,该方法用于显示的输出。fmt.Println()是一个标准的库函数,用于将某些内容打印为屏幕上的输出,fmt包已包含了Println方法,该方法用于显示输出。
- 注释: 注释用于解释代码,并且以与Java或C或C ++类似的方式使用。编译器将忽略注释条目,并且不执行它们。注释可以是单行或多行。