1. Go安装
1.1. 下载地址
Go官网下载地址:https://golang.org/dl/
Go官方镜像站:https://golang.google.cn/dl/
1.2. windows配置环境变量
1.2.1. PATH
1.2.2. GOPATH
GOPATH是一个环境变量,用来表明你写的go项目的存放路径(工作目录)。GOPATH路径最好只设置一个,所有的项目代码都放到GOPATH的src目录下。Go1.11版本之后,开启go mod模式之后就不再强制需要配置GOPATH了。
1.2.3. 添加GOPATH到PATH
1.3. Linux下配置环境变量
参考: https://www.yuque.com/duduniao/go/hjzb#1DfPg
2. Go开发环境
2.1. GOPATH
在v1.11版本之前,go工程代码需要放在 $GOPATH/src下,这种管理方式存在一个很大问题:第三方包和源码同放在一个目录下,而且还缺乏版本控制!因此在go1.11 之后的版本中,开发者基本不再使用gopath方式进行开发。
2.2. GOMOD
Gomod在v1.11版本推出,在v1.14中足够成熟,可以用于生产环境,Gomod可以让项目目录不再约束在$GOPATH/src下,此时不同的项目可以使用同一个第三方库的不同版本。在推出gomod之后,基本没必要再使用老的GOPATH模式进行开发。
2.2.1. 初始化git仓库
此处以gitee仓库为例,如果只是本地开发,可以跳过该步骤
[root@duduniao gitee]# mkdir go-learn[root@duduniao gitee]# cd go-learn/[root@duduniao go-learn]# git initInitialized empty Git repository in /opt/projects/gitee/go-learn/.git/[root@duduniao go-learn]# git config user.name "渡渡鸟"[root@duduniao go-learn]# git config user.email "duduniao@qq.com"[root@duduniao go-learn]# touch README.md[root@duduniao go-learn]# git add README.md[root@duduniao go-learn]# git commit -m "first commit"[root@duduniao go-learn]# git remote add origin git@gitee.com:linux_duduniao/go-learn.git[root@duduniao go-learn]# git push -u origin master[root@duduniao go-learn]# git branch develop[root@duduniao go-learn]# git checkout developSwitched to branch 'develop'[root@duduniao go-learn]# git branch -a* developmasterremotes/origin/master
2.2.2. 简单使用gomod
初始化项目
[root@duduniao go-learn]# go mod init gitee.com/linux_duduniao/go-learn # 创建gomod项目
编写一个简单的go代码 ```go [root@duduniao go-learn]# vim main.go package main
import ( // 导入日志模块 logger “github.com/sirupsen/logrus” )
func main() { logger.Info(“test”) }
- 生成gomod依赖
生成gomod依赖
[root@duduniao go-learn]# go mod tidy
go.mod 文件内容
[root@duduniao go-learn]# cat go.mod module gitee.com/linux_duduniao/go-learn
go 1.16
require github.com/sirupsen/logrus v1.8.1
go.sum 文件内容
[root@duduniao go-learn]# cat go.sum github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
<a name="fhb3u"></a>### 2.2.3. gomod深入学习以下部分适合已经学习过一段时间golang开发同学学习!**本章节参考的是**[** anqiansong **](https://github.com/anqiansong/golang-notes/blob/main/go-module.md)**笔记和 [官方文档](https://golang.org/ref/mod) **!<br />gomodule 有两个关键文件:go.mod 和 go.sum,go.mod文件是学习gomod的关键<a name="ZcfPM"></a>#### 2.2.3.1. go.mod```gomodule gitee.com/linux_duduniao/go-learngo 1.16require (gitee.com/linux_duduniao/apiserver v0.0.0github.com/Microsoft/go-winio v0.5.0 // indirectgithub.com/containerd/containerd v1.5.2 // indirectgithub.com/docker/docker v20.10.7+incompatiblegithub.com/docker/go-connections v0.4.0 // indirectgithub.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirectgithub.com/morikuni/aec v1.0.0 // indirectgithub.com/sirupsen/logrus v1.8.1golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirectgolang.org/x/net v0.0.0-20210614182718-04defd469f4e // indirectgolang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914 // indirectgolang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirectgolang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirectgolang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6 // indirectgoogle.golang.org/appengine v1.6.7 // indirectgoogle.golang.org/genproto v0.0.0-20210708141623-e76da96a951f // indirectgoogle.golang.org/grpc v1.39.0 // indirectgopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirectk8s.io/api v0.21.2 // indirectk8s.io/apimachinery v0.21.2k8s.io/client-go v0.21.2k8s.io/klog/v2 v2.9.0 // indirectk8s.io/utils v0.0.0-20210709001253-0e1f9d693477 // indirectsigs.k8s.io/structured-merge-diff/v4 v4.1.2 // indirect)replace (gitee.com/linux_duduniao/apiserver => ./src/apiserver)excule (k8s.io/client-go v0.21.0)
以上的 go.mod 文件中,line 1 表示当前工程项目的模块名称; line 3 表示当前使用的 go mod init 时使用的go语言版本。require 代码块表示当前项目依赖的模块。
- require 的版本号问题:
版本号格式为: v{major}.{minor}.{patch} ,一般而言,当 major 为0或者 patch 带有 pre, beta 时,表示版本不稳定。上述的 line 11、line 14 是伪版本号,会增加时间戳和修订标识符。
在gomod推荐的版本管理系统中,建议将 major 写在模块名称末尾,比如当前go-learn的Tag到v3.0.0时,module应当修改为 gitee.com/linux_duduniao/go-learn/v3 。如果没有修改 go.mod 或者不存在 go.mod ,被引用时,会打上 +incompatible 标志
- indirect 含义
indirect 表示间接依赖,当项目A引用B,B引用C1和C2时:如果B没有启用go.mod,则C1,C2作为间接引用出现在A的go.mod文件中。当B启用了go.mod,但是C2不在其go.mod中时,C2作为间接引用出现在 A 的go.mod中。使用 go mod why -m pkg 可以显示为啥依赖该模块。
- replace的使用
replace 用于替换require中的依赖,一般有以下三种情况会使用到:
- 替换无法下载的包,如使用 github 中的包替换其它 URL 地址或版本的包
- 替换本地自己的包,如 line 33
- 替换fork的包,部分场景中需要对第三方包做修改且作为公共包对外时,会考虑fork一个到自己的仓库
- exclude
2.2.3.2. go.sum
go.sum 用于记录各个依赖包版本的摘要,如果该依赖有 go.sum 还会记录 go.sum 的摘要。目的是用于防止依赖包被篡改,因为第三方模块的tag可能会被篡改,导致项目出现风险。go.sum 记录的依赖版本可能会比go.sum中使用到的多得多,这个并不会影响项目本地。在提交代码时,需要把 go.sum 和 go.mod 同时提交。当go.sum 合并分支发生冲突时,一般将两个go.sum文件内容合并后保存。
2.2.4. gomod常用指令
2.2.4.1. 环境变量
参考文档:goproxy.io
1. GO111MODULEGO111MODULE(111是指v1.11版本) 环境变量,该变量的值有三个:• off: 禁用gomod模块,编译时从 GOPATH和vendor目录下查找• on: 启用gomod模块,编译忽略GOPATH和vendor目录,只根据go.mod下载依赖• auto(默认值): 当项目在$GOPATH/src之外,且根目录存在go.mod文件时,启用gomod模块2. GOPROXYGOPROXY指定下载go模块的代理服务器地址,用于解决国内互联网环境访问国际互联网高延迟问题。https://goproxy.cn 是最常用,也是最稳定的国内代理,由七牛云支持的非盈利项目。• 推荐在go1.13之后使用,配置GOPROXY=https://goproxy.cn,direct,其中direct是go1.13提供的特性,当goproxy无法访问的适合会直接访问模块地址,一定程度上解决私有库问题• 在go1.13之前使用 GOPROXY=https://goproxy.cn 指定私有库,不过在go1.13之前gomod也是非稳定功能3. GOPRIVATEGOPRIVATE指定私有库地址,使得直接跳过GOPROXY和GOSUMDB,可以用逗号分隔多个域名,也支持*的泛域名如: GOPRIVATE=gitlab.ddn.com4. GOSUMDB该变量用于指定go.sum中摘要验证的数据库,golang为了第三方包的安全性,对第三方包的摘要做了数据库,地址为sum.golang.org当设置了GOPROXY="https://proxy.golang.org"时,GOSUMDB指向"sum.golang.org",其它情况下默认关闭。如果配置了GOPROXY为其它值,且需要开启摘要检验,可以指定为国内的gosum.ioGOSUMDB=gosum.io+ce6e7565+AY5qEHUk/qmHc5btzW45JVoENfazw8LielDsaI+lEbq6当GOSUMDB为off时,明确指定不启用摘要校验,go get 指定 -insecure 也可以跳过校验5. GONOSUMDB如果启用了GOSUMDB,且没有配置GOPRIVATE,那么需要指定GONOSUMDB,用于跳过不校验摘要的依赖,多个域名用分号分隔如: GONOSUMDB=*.ddn.com
2.2.4.2. 相关指令
1. go mod init [module]初始化gomod,会在项目目录下生成 go.mod 文件,如: go mod init github/duduniao/application.如果是v2以上版本,golang建议在项目末尾加上大版本,如: github/duduniao/application/v32. go mod tidy [-e] [-v]更新go.mod文件,移除不必要的模块,添加新的模块。-e: 在遇到错误的时候尽量继续-v: 显示移除的模块3. go mod download [-json] [-x] [modules]用于下载模块到gomod缓存目录下。-jons: 以json对象打印下载的模块信息-x: 默认donwload不会打印标准输出,只打印标准错误,使用-x打印执行过程到标准错误modules: 指定要下载的模块,可以是模块名@version,如果不指定modules,则下载所有go.mod中依赖4. go mod edit [flags] [-fmt|-print|-json] [go.mod]编辑go.mod文件,如添加、修改、删除go.mod内容。flags: flags 分为以下几种:• -module: 用于修改模块路径• -go=version: 修改golang版本• -require=path@version: 添加require的模块• -droprequire=path: 移除require的模块• -replace=old[@v]=new[@v]: 替换模块,当new省略version,仅用于new为相对路径,不能为本项目目录之外的代码库• -dropreplace=old[@v]: 移除replace中的模块• -exclude=path@version, -dropexclude=path@version: 添加或移除模块-fmt: 格式化go.mod文件-print: 打印go.mod文件,以文本的形式-josn: 打印go.mod文件,以json格式5. go mod verify校验模块的摘要信息6. go mod why [-m] [-vendor] packages...打印为什么需要引入这个包7. go mod vendor [-e] [-v]将go.mod中用的模块从缓存目录迁移到项目根目录下的 vendor 目录下,这个目录可能会很大。大部分情况下这个命令是没必要执行的,部分场景中由于CI过程中拉取代码存在问题才会考虑从vendor目录下获取依赖进行编译当启用了 vendor 目录,编译和运行时指定 -mod=vendor 表示从vendor目录读取依赖而不是缓存中
2.3. 笔者Go项目开发环境
环境: win10 + wsl2(Ubuntu2004) + vscode + golang, 并不是最优解,仅供参考!
当具备一定的golang基础后,一定要打造一个对你而言最佳的golang开发环境,这样对效率的提升是非常大的!
2.3.1. 安装wsl2和ubuntu2004
初学者不需要纠结工具,选择 goland 或者 vscode 在win10下开发可能更方便,当需要linux环境时,再考虑远程开发!
笔者是因为部分项目,需要Linux环境,并且笔者运维出身,对Linux命令行和shell非常熟悉,同时ubuntu2004可以更好的运行docker和CICD工具,可以在Linux场景下提升开发效率,所以才选择 wsl2 环境。
等待wsl2 GUIAPP 进入稳定版后,推荐使用 goland + wsl2 进行开发,这样效率会更高! 参考博客
- 安装WSL2子系统
-
terminal 配置文件:settings.json
2.3.2. 安装golang
```
golang各版本安装目录
[root@duduniao ~]# ls -l /opt/release/golang/ total 24 drwxr-xr-x 4 root root 4096 Jan 30 11:38 gopath drwxr-xr-x 10 root root 4096 Feb 13 2020 v1.12.17 drwxr-xr-x 10 root root 4096 Aug 6 2020 v1.13.15 drwxr-xr-x 10 root root 4096 Jan 20 04:10 v1.14.14 drwxr-xr-x 10 root root 4096 Mar 12 01:13 v1.15.10 drwxr-xr-x 10 root root 4096 Jun 6 18:09 v1.16.2 [root@duduniao ~]# ls -l /opt/apps/go* -d lrwxrwxrwx 1 root root 27 Jun 6 18:09 /opt/apps/golang -> /opt/release/golang/v1.16.2 lrwxrwxrwx 1 root root 26 Jul 10 17:18 /opt/apps/gopath -> /opt/release/golang/gopath
环境变量配置
[root@duduniao ~]# cat .bash/exports export GOPATH=/opt/apps/gopath export BASE_PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/root/bin export PATH=$BASE_PATH:$GOPATH/bin
export GO111MODULE=on export GOPROXY=https://goproxy.cn,direct export GOPRIVATE=gitlab.local.com export CGO_ENABLED=0 export GOOS=linux export GOARCH=amd64
默认的go解释器
export GOROOT=/opt/apps/golang export PATH=$BASE_PATH:$GOROOT/bin export GOCACHE=/tmp/gocache
命令别名,在命令行可以快速切换不同版本的go环境
[root@duduniao ~]# cat .bash/aliases
本地访问国际互联网的代理服务器,用于下载golang依赖包
alias proxy=’export https_proxy=http://10.4.7.1:10080;export http_proxy=http://10.4.7.1:10080‘ alias unproxy=’unset https_proxy;unset http_proxy’
不同golang环境切换
alias go12=’export GOROOT=/opt/release/golang/v1.12.17; export PATH=$GOROOT/bin:$BASE_PATH’ alias go13=’export GOROOT=/opt/release/golang/v1.13.15; export PATH=$GOROOT/bin:$BASE_PATH’ alias go14=’export GOROOT=/opt/release/golang/v1.14.14; export PATH=$GOROOT/bin:$BASE_PATH’ alias go15=’export GOROOT=/opt/release/golang/v1.15.10; export PATH=$GOROOT/bin:$BASE_PATH’ alias go16=’export GOROOT=/opt/release/golang/v1.16.2; export PATH=$GOROOT/bin:$BASE_PATH’
应用以上配置
[root@duduniao ~]# cat .bashrc ……
sources
files=”/root/.bash/exports /root/.bash/aliases /root/.bash/commands /etc/bash_completion /usr/share/bash-completion/bash_completion” for i in $files do [ -e $i ] && source $i done ……
项目存放目录
[root@duduniao ~]# tree -L 2 /opt/projects/ /opt/projects/ ├── gitee │ ├── application │ └── image ├── gitlab │ └── k3s └── local └── ro_intaller
<a name="U1Rmh"></a>### 2.3.3. vscode配置参考文档:- [https://zhuanlan.zhihu.com/p/320343679](https://zhuanlan.zhihu.com/p/320343679)- [https://code.visualstudio.com/docs](https://code.visualstudio.com/docs)---<a name="bE249"></a># 3. Go语言的基础语法```go// main.gopackage mainimport "fmt"var testString string = "hello world!"func main() {fmt.Println(testString)}
3.1. 语言结构
- 定义包名:
package main,在代码文件的非注释的第一行指定当前的代码文件属于哪个包。main表示一个可独立执行的程序 - 导入包:
import "fmt",使用import导入其它的包 - 变量:
var testString string = "hello world!",自定义变量 函数:
func main() {...},函数。其中main()函数为入口函数,可独立运行的项目会有一个main函数3.2. 基础语法
注释:单行注释用双斜线
//,多行注释用/* ..... */,一般使用单行注释- 语句:建议一行一个语句,Go会自动对每一行后面添加
; - 代码块:代码块用
{ ... }表示 - 标识符:标识符一般采用小驼峰式命名,如
studentName,首字母大写表示对当前Package之外可见3.3. 编译和运行程序
golang 是静态语言,需要编译后才能执行: ``` [root@duduniao go-learn]# gofmt -w main.go # 格式化代码,用于统一代码风格 [root@duduniao go-learn]# go run main.go # 直接运行,其实是经历了编译,再运行 hello world!
[root@duduniao go-learn]# go build main.go # go build 表示编译,默认编译后的二进制文件存放到当前目录下 [root@duduniao go-learn]# ls README.md go.mod go.sum main main.go [root@duduniao go-learn]# ./main # 运行编译后的二进制文件 hello world!
[root@duduniao go-learn]# go build -o /tmp/hello_world main.go # 指定编译后二进制文件存放路径 [root@duduniao go-learn]# /tmp/hello_world hello world!
跨平台编译
CGO代码不支持跨平台编译,因此设置 CGO_ENABLED=0 ,设置平台 GOOS=linux|windows|darwin ,分别对应linux、windows、mac,架构GOARCH=amd64
如在windows编译成可以在linux执行的二进制文件
SET CGO_ENABLED=0 SET GOOS=linux SET GOARCH=amd64 go build ```
3.4. Go语言相关资料
Go语言官网: https://golang.org/
Go语言标准库: https://books.studygolang.com/The-Golang-Standard-Library-by-Example/;https://studygolang.com/pkgdoc
Go官方指南: https://tour.go-zh.org/welcome/1
李文周博客: https://www.liwenzhou.com/posts/Go/go_menu/
