Go语言入门
GO语言介绍
最近在学习Golang,Go 语言被设计成一门应用于搭载 Web 服务器,存储集群或类似用途的巨型中央服务器的系统编程语言。
对于高性能分布式系统领域而言,Go 语言无疑比大多数其它语言有着更高的开发效率。它提供了海量并行的支持,这对于游戏服务端的开发而言是再好不过了。
1:特点
- 编译型语言,有比较充分的编译期检查。
- 强类型语言,安全,速度快。
- 严格区分值和指针。
- 机器码目标编译器,不依赖虚拟机。
- 类C逻辑,很多特性与C语言一脉相承,又有很多现代化改进。
- 支持多返回值。
- 有GC。
- 协程模型,屏蔽了os线程概念,抽象了多线程软件开发。
- 基于消息传递的通信方式。
- 支持反射。
- defer善后处理方式。
- 支持嵌入C语言,汇编语言。
- 跨平台,arm,mips,x86,win,linux,macos,freebsd,设计本身对新平台扩展也很友好。
- 原生支持跨平台交叉编译。
- 用tags代替了C中的宏,更易读,易管理。
- 统一代码风格,全世界的go代码读起来都像自己写的。
- 编译速度非常快,在编译成机器码的语言中来说,有当年delphi的感觉。
- 完善的工具链,编译,调试,测试,文档,性能分析,代码管理,模块管理,版本管理,全部自带,不依赖第三方。
- 面向工程的语言,没有太多新潮的功能。
- 默认UTF-8编码。
2:优势
- 有C基础的话,学习成本极低。
- 自带功能非常丰富的标准库,许多高级功能基本不需要找三方库。
- 语言和编译期已经稳定,版本升级很谨慎,持续保持兼容性。
- 运行速度快占用资源少,运行速度不输主流的java/c#,占用资源却少很多。
- 不需要考虑内存泄露的C语言?
- 实施简单,通常只需要copy一个可执行文件。
- 与C语言结合机制简单,相比JNI。
- 机器码目标程序增加了破解和反编译难度。
- 只有一套标准和知识,起码目前还没有分裂。
- 交叉编译特别简单方便。
3:劣势
- 没有真正的面向对象,有类C风格基本的对象和接口组合功能。
- 错误处理比较原始(官方认为这样很好),逻辑控制需要耗费更多精力。
- 包依赖要求比较严格的C风格,管理不当容易产生循环依赖错误。
- 没有动态特性,一切都在编译期定了。
- 需要精细粒度控制资源的领域无法取代C。
- 编译时要求拥有全部源代码,没开放类似c的lib功能。
- 三方包著名的较少,选择困难,很多问题还要自己来。
- 官方没有提供GUI开发包,虽然有一些开源实现,但还不适合任复杂图形界面开发。
- 移动前端开发还不成熟。
- 自带模板引擎功能很弱,不是很好用,一般需要自行扩展。
- 相比java,没那么适合堆集木。
1 |
|
Go module
1、go module介绍
在早期编写Go项目时,需要将Go项目代码依赖的所有第三方包放入GOPATH
目录下,这是方式的缺点在于不支持版本管理,同一个依赖包只能存在一个版本的代码。而多个项目下可能会分别使用不同版本的依赖包。
在Go1.11版本中,发布了Go module
的依赖管理方式,可以帮助开发人员更方便地管理项目依赖,并且保证依赖的版本管理和代码的可复用性。Go module在Go1.14 版本开始推荐在生产环境使用,于Go1.16版本默认开启。
具体来说,Go module
将依赖包版本信息和程序代码本身实现分离管理,每个Go module
都会有一个go.mod
文件,该文件包含了module
的依赖包列表以及对应的版本信息,当一个module
需要引用其他依赖包时,会根据go.mod
文件中的信息去下载对应的依赖包和对应版本的代码供程序使用。
2、go module相关命令
命令 | 说明 |
---|---|
go mod init | 初始化项目依赖,生成go.mod 文件 |
go mod download | 下载 go.mod 文件中指明的所有依赖 |
go mod tidy | 检查项目中的依赖关系,项目文件中引入的依赖与 go.mod 进行比对 |
go mod graph | 打印出模块依赖图,显示项目中所有模块及其之间的依赖关系 |
go mod edit | 编辑 go.mod 文件 |
go mod vendor | 将当前项目的依赖项复制到项目的 vendor 目录中,以便离线构建和依赖管理 |
go mod verify | 校验项目中的依赖项是否被篡改过,以保证项目依赖的完整性和安全性 |
go mod why | 显示指定模块依赖关系的原因,即为什么当前模块需要依赖该指定模块 |
3、go module相关env配置
在Go module中,可以通过go env
命令查看常用环境变量。
GO111MODULE
在环境变量中,GO111MODULE
变量作为Go modules
的开关,其允许设置如下参数:
-
auto
:项目若包含go.mod文件,则启用Go modules
; -
on
:启用Go modules
,go命令行会使用modules,而不会去GOPATH
目录下查找依赖包,推荐设置; -
off
:禁用Go modules
,寻找依赖包的方式沿用旧版本通过vendor
目录或者GOPATH
模式来查找,不推荐设置;
如果需要对GO111MODULE
环境变量的值进行变更,则可以使用如下命令:
1 |
|
GOPROXY
GOPROXY
环境变量主要用于设置Go模块代理(Go module proxy
),使Go在后续拉取依赖时能够脱离传统的VCS(版本控制系统)方式,直接通过镜像站点快速拉取。
GOPROXY
的默认值是:https://proxy.golang.org,direct
,该站点在国内无法正常访问,因此在开启Go modules时,需要设置国内的Go模块代理。目前社区使用比较多的有两个https://goproxy.cn
和https://goproxy.io
。执行命令如下:
1 |
|
GOPROXY
允许设置多个模块代理地址,多个地址之间以英文逗号“,”分隔开,若不想使用,则可以设置为“off”,这将会禁止Go在后续操作中使用任何的Go模块代理。
direct
是一个特殊指示符,用于只是Go回到模块版本的源地址去抓取,例如GitHub。当配置多个代理地址时,值代理地址列表中上一个Go模块代理地址返回404 或 410 错误时,Go 会自动尝试下一个模块代理地址,当遇到 direct
时会回到源地址去抓取,当遇到EOF
时中止并抛出错误。
GOSUMDB
GOSUMDB
环境变量(Go checksum database)在拉取依赖版本时(无论是在源站点还是Go module proxy)保证拉取的模块版本数据未经过篡改,若发现不一致,即可能存在篡改,则会立即中止拉取。
GOSUMDB
的默认值为sum.golang.org
,该站点在国内无法访问,不过可以通过之前设置的GOPROXY
解决,GOPROXY
设置的代理goproxy.cn
同样支持代理sum.golang.org
。
若该值设置为off
,则禁止GO在后续操作中校验模块版本。
4、使用go module
通过一个案例,在开发项目时可以更好的理解和使用go module拉取和管理依赖。
在本地新建一个名为testProject
的项目目录,并切换到该目录下:
1 |
|
在testProject
项目目录下,初始化创建一个go.mod
文件。
1 |
|
使用该命令后自动会在项目目录下创建一个go.mod
文件,内容如下:
1 |
|
-
module testProject
:表示当前项目的导入路径; -
go 1.19
:表示当前项目使用的Go版本;
go.mod
文件会记录项目中使用的第三方依赖包信息,包括包名和版本,但由于目前项目并未使用到任何第三方包,因此go.mod
文件暂时还没有记录任何依赖包信息。
可以在项目的目录下创建一个main.go
文件,然后使用go get
命令手动下载一个依赖包来测试一下:
1 |
|
可以看到调用go get
命令后,将依赖添加到项目中,前缀 go: added
表示成功添加了一个新的依赖包。此时go.mod中的内容:
1 |
|
从上述go.mod
文件中记录的当前项目中所有依赖包的相关信息可知,声明依赖的格式如下:
1 |
|
-
require
:声明依赖包的关键字; -
module/path
:依赖包的导入路径; -
v1.2.3
:依赖包的版本号,支持latest
最新版本、详细版本v1.2.3
、指定某次commit hash
这几种格式。
在导入了指定的依赖包后,此时可以在main.go文件中使用导入的依赖包,例如:
1 |
|
使用go build
生成.exe
可执行文件后,执行生成的可执行文件后,在浏览器中输入http://localhost:8080/
则可以看到Hello, World!
打印。
通过案例可以了解到,在创建项目后,如果需要使用go module
,则需要将go env
中的GO111MODULE
环境变量设置成on
,打开go module
模式。打开后,可以到项目目录下,执行go mod init
初始化生成 go.mod
文件。如果需要导入指定版本的第三方依赖包,则可以使用go get
命令进行下载。
执行go get
命令,在下载依赖包的同时还可以指定依赖包的版本。
-
go get -u
命令会将项目中的依赖包升级到最新的次要版本或者修订版本; -
go get -u=patch
命令会将项目中的依赖包包升级到最新的修订版本; -
go get [包名]@[版本号]
命令会下载对应依赖包的指定版本或者将对应包升级到指定的版本,例如go get foo@v1.2.3
。
go module
安装依赖包时先拉取最新的 release tag
,若无 tag
则拉取最新的 commit
,且go项目会自动生成一个 go.sum
文件来记录 dependency tree
。go module
引入了go.sum
机制来对依赖包进行校验。
另外,go module
会把下载到本地的依赖包会以类似下面的形式保存在 $GOPATH/pkg/mod
目录下,每个依赖包都会带有版本号进行区分,这样就允许在本地存在同一个包的多个不同版本。
1 |
|
如果想清除所有本地已缓存的依赖包数据,可以执行 go clean -modcache
命令。
建立一个Go项目
我随便找了个路径建立了一个 文件夹,D:\GoAllStudyProject\FirstDemo,打开cmd输入命令go mod init FirstDemo
1 |
|
此时会创建一个go.mod文件,这个时候我们可以导入Gin框架来搭建Web,
Gin 是一个用 Go (Golang) 编写的 HTTP web 框架。 它是一个类似于 martini 但拥有更好性能的 API 框架, 优于 httprouter,速度提高了近 40 倍。(以上为官网描述)
我们使用命令
1 |
|
此时会多出一个go.sum文件,我们在D:\GoAllStudyProject\FirstDemo 建立一个main.go文件,
1 |
|
然后我们运行这个main函数,访问localhost:8080,我们就能看到服务启动成功,此时我们的项目就搭建完成了,我们可以访问localhost:8080/user,此时可以看到
{
“name”: “张三”,
“age”: 20
}
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!