golang学习笔记(基于1.22,持续更新)

1、安装和环境变量,代理配置

  • GOROOT:安装 go 的路径。包含了 Go 语言的标准库、编译器等工具。在使用 Go 编译器、运行时等工具时,它们会默认从 GOROOT 中查找相关的文件。如下:

  

   系统模块位于src目录下。

   一般情况下,我们不需要修改 GOROOT 的值,除非要更换go版本。

  • GOPATH:指定了 Go 语言工作区的路径,它包含了你的项目源代码、依赖库以及编译后的可执行文件等。在使用 Go 工具链时,它们会默认从 GOPATH 中查找相关的文件。如果你的项目依赖了第三方库,那么这些库也会被下载到 GOPATH 目录下。在使用 Go Modules 进行依赖管理时,GOPATH 的作用会被降低,因为 Go Modules 可以将依赖库放在任何地方,不需要将其放在 GOPATH 目录下。

    这个下面会自动生成 bin(go build默认构建于当前目录,go install会将其移动到本目录),pkg 和 src 文件夹, 他们都是你的go项目运行中比较重要的文件夹。 bin文件夹下保存了所有通过go install安装的工具的可执行命令,可通过GOBIN修改, pkg里面是一些依赖的库文件,如xx.a文件, src 是你下载的依赖的源码文件。
C:\Users\zjhua\go 的目录

2024/08/04 19:53 <DIR> .
2024/08/04 19:53 <DIR> ..
2024/08/04 19:53 <DIR> bin
2024/08/04 19:52 <DIR> pkg
  • GOBIN go的可执行路径,默认位于GOPATH/bin 目录,这个路径决定了你执行go install后的编译文件的安装路径,需要将他加入到你的系统PATH环境变量中;
  • GO111MODULE 这个是用来控制go的运行模式是模块方式还是GOPATH模式;
  • GOARCH 系统架构,如 amd64, 386, arm, ppc64 , 这个配置不合适代码直接无法运行;
  • GOOS 这个也是一个很常用的变量,他返回当前操作系统的名称, 如 linux, darwin, windows, netbsd;
  • 还有一个在打包编译的时候经常用到 CGO_ENABLED 是否启用cgo, 一般都是0 禁用。

 go env可以查看当前系统中所有的环境变量,如下:

复制代码
C:\Users\zjhua\go\bin>go env
set GO111MODULE=
set GOARCH=amd64
set GOBIN=
set GOCACHE=C:\Users\zjhua\AppData\Local\go-build
set GOENV=C:\Users\zjhua\AppData\Roaming\go\env
set GOEXE=.exe
set GOEXPERIMENT=
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOINSECURE=
set GOMODCACHE=C:\Users\zjhua\go\pkg\mod
set GONOPROXY=
set GONOSUMDB=
set GOOS=windows
set GOPATH=C:\Users\zjhua\go
set GOPRIVATE=
set GOPROXY=https://goproxy.cn,direct
set GOROOT=C:\Program Files\Go
set GOSUMDB=sum.golang.org
set GOTMPDIR=
set GOTOOLDIR=C:\Program Files\Go\pkg\tool\windows_amd64
set GOVCS=
set GOVERSION=go1.20.14
set GCCGO=gccgo
set GOAMD64=v1
set AR=ar
set CC=gcc
set CXX=g++
set CGO_ENABLED=0
set GOMOD=NUL
set GOWORK=
set CGO_CFLAGS=-O2 -g
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-O2 -g
set CGO_FFLAGS=-O2 -g
set CGO_LDFLAGS=-O2 -g
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-m64 -fno-caret-diagnostics -Qunused-arguments -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=C:\Users\zjhua\AppData\Local\Temp\go-build3641988413=/tmp/go-build -gno-record-gcc-switches
复制代码

默认值除了通过环境变量配置外,也可以通过go env -w <NAME>=<VALUE>进行修改,哪种好看开发的偏好。

详细可见:https://zhuanlan.zhihu.com/p/700034911

1.1 三方包仓库

  和maven、python等一样,go的中央仓库https://proxy.golang.org/也是被墙了,所以需要配置代理。如下:

  go env -w GOPROXY=https://goproxy.cn,direct

2、工程结构与模块化、初始化与依赖安装(离线)

2.1 创建工程脚手架

  go mod init [yourcompany.com/level1_produdct_name/level2_product_name]

  一般和maven的模块化类似。模块名相当于Java工程的包名,其它模块依赖它会依赖于改URI,所以取名要慎重。

2.2 下载三方依赖

  go get命令向项目添加依赖。go.mod文件将跟踪模块的依赖关系和版本。

  例如添加mvc依赖,D:\go-demo> go get github.com/gin-gonic/gin

复制代码
PS D:\go-demo> go get github.com/gin-gonic/gin
go: downloading github.com/gin-gonic/gin v1.10.0
go: downloading github.com/gin-contrib/sse v0.1.0
go: downloading github.com/mattn/go-isatty v0.0.20
go: downloading golang.org/x/net v0.25.0
go: downloading github.com/go-playground/validator/v10 v10.20.0
go: downloading github.com/ugorji/go/codec v1.2.12    
go: downloading github.com/pelletier/go-toml/v2 v2.2.2
go: downloading google.golang.org/protobuf v1.34.1
go: downloading gopkg.in/yaml.v3 v3.0.1
go: downloading github.com/bytedance/sonic v1.11.6
go: downloading github.com/goccy/go-json v0.10.2
go: downloading github.com/json-iterator/go v1.1.12
go: downloading golang.org/x/sys v0.20.0
go: downloading github.com/gabriel-vasile/mimetype v1.4.3
go: downloading github.com/go-playground/universal-translator v0.18.1
go: downloading github.com/leodido/go-urn v1.4.0
go: downloading golang.org/x/crypto v0.23.0
go: downloading golang.org/x/text v0.15.0
go: downloading github.com/go-playground/locales v0.14.1
go: downloading github.com/modern-go/reflect2 v1.0.2
go: downloading github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd
go: downloading github.com/cloudwego/base64x v0.1.4
go: downloading github.com/klauspost/cpuid/v2 v2.2.7
go: downloading golang.org/x/arch v0.8.0
go: downloading github.com/bytedance/sonic/loader v0.1.1
go: downloading github.com/twitchyliquid64/golang-asm v0.15.1
go: downloading github.com/cloudwego/iasm v0.2.0
go: added github.com/bytedance/sonic v1.11.6
go: added github.com/bytedance/sonic/loader v0.1.1
go: added github.com/cloudwego/base64x v0.1.4
go: added github.com/cloudwego/iasm v0.2.0
go: added github.com/gabriel-vasile/mimetype v1.4.3
go: added github.com/gin-contrib/sse v0.1.0
go: added github.com/gin-contrib/sse v0.1.0
go: added github.com/gin-gonic/gin v1.10.0
go: added github.com/go-playground/locales v0.14.1
go: added github.com/go-playground/universal-translator v0.18.1
go: added github.com/gin-gonic/gin v1.10.0
go: added github.com/go-playground/locales v0.14.1
go: added github.com/go-playground/universal-translator v0.18.1
go: added github.com/go-playground/locales v0.14.1
go: added github.com/go-playground/universal-translator v0.18.1
go: added github.com/go-playground/validator/v10 v10.20.0
go: added github.com/go-playground/validator/v10 v10.20.0
go: added github.com/goccy/go-json v0.10.2
go: added github.com/json-iterator/go v1.1.12
go: added github.com/goccy/go-json v0.10.2
go: added github.com/json-iterator/go v1.1.12
go: added github.com/klauspost/cpuid/v2 v2.2.7
go: added github.com/leodido/go-urn v1.4.0
go: added github.com/mattn/go-isatty v0.0.20
go: added github.com/mattn/go-isatty v0.0.20
go: added github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd
go: added github.com/modern-go/reflect2 v1.0.2
go: added github.com/pelletier/go-toml/v2 v2.2.2
go: added github.com/twitchyliquid64/golang-asm v0.15.1
go: added github.com/ugorji/go/codec v1.2.12
go: added golang.org/x/arch v0.8.0
go: added golang.org/x/crypto v0.23.0
go: added golang.org/x/net v0.25.0
go: added golang.org/x/sys v0.20.0
go: added golang.org/x/text v0.15.0
go: added google.golang.org/protobuf v1.34.1
go: added gopkg.in/yaml.v3 v3.0.1
复制代码

  go get会一并加载依赖的库。除了使用go get module_name外,当然也可以人工编辑go.mod加载依赖(和maven的做法一样),但是这样的话,运行go build、go run 或 go test等构建命令时,会抱怨以来不正确。如下:

PS D:\go-demo> go build
go: finding module for package github.com/lib/pq
main.go:7:2: cannot query module due to -mod=vendor
(Go version in go.mod is at least 1.14 and vendor directory exists.)

  此时,仍然需要通过go get重新拉取依赖。所以,尽量使用go get和go mod tidy管理依赖。

  除此之外,go get还会创建一个go.sum的文件,如下:

  里面是 Go 语言项目中的摘要文件,用于记录项目的依赖项的版本和哈希值。格式如下:

  module/path/version go.mod_checksum

  其中,module/path/version`是依赖项的模块路径和版本号,go.mod_checksum 是对应的 go.mod文件的哈希值。

  当使用:go get、go build、go run等命令时,Go 工具会检查 go.sum 文件,根据其中的哈希值验证依赖项的完整性。如果依赖项的哈希值与 go.sum 文件中记录的值不匹配,将会引发错误,防止使用被篡改或非预期的依赖项。

  同时,go.sum 文件还可以用于将项目的依赖项锁定到特定的版本,以确保在构建和部署过程中使用相同的依赖版本。这有助于保持项目的可重复性和稳定性。

  请注意,不能手动编辑 go.sum 文件,它应该由 Go 工具自动生成和维护。如果需要更新或修改依赖项,应该使用 go get 命令或手动更新项目的 go.mod 文件,并让 Go 工具自动更新 go.sum 文件。

2.2.1 三方库的标准仓库位置是:https://pkg.go.dev/search?q=json,基本上和maven、postgresql、python依赖类似。模块的坐标就是:https://pkg.go.dev后面的部分,如https://pkg.go.dev/encoding/json的模块是encoding/json。

2.3 锁定版本 go mod vendor

  使用go mod管理go的第三方包依赖,就像java项目使用maven一样,通过go mod vendor就可以将mod依赖的第三方库下载并生成到vendor目录下,这个目录就像java项目中导入jar到项目路径一样,当mod依赖的项目在vendor中能直接找到,就不会使用mod远程下载到本地并引用。如下:

  这样的好处比如项目完成后第三方依赖包几乎不会改变,那么就可以发送带有vendor的项目给朋友开发,朋友拿到项目,看到有vendor就直接不用考虑依赖的包,mod依赖优先加载vendor中的依赖,也不会从网络上下载不知所云的包,只有用到的包才会在vendor中出现。vendor好处是在mod中无论是引用的第三方库版本是多少,只有vendor中出现就会忽略你使用的版本,因为mod会优先加载vendor中的依赖,并忽略版本,如果通过mod本地管理的库会按照指定版本导入,如果没有就下载。

  所以,为了依赖的三方库的稳定性,应通过在新增依赖时统一执行go mod vendor,把各个go模块依赖的三方库复制到项目根目录的vendor目录下。解决了离线开发与构建、版本锁定和一致性两个问题。

  注:如果go mod vendor报代理相关错误,可通过执行go env -w GOSUMDB=off关闭包的有效性验证。

  也可以配置为go env -w GOSUMDB="sum.golang.google.cn",国内专用。

2.4 保持三方库的紧凑和干净

  go mod tidy 命令是 Go Modules 提供的一个有用工具,用于确保项目的 go.mod 文件和其依赖项保持同步并得到正确管理。它有助于通过添加缺失或删除未使用的依赖项来清理 go.mod 文件,确保模块的要求是准确且最新的。例如,先添加一个mysql库的依赖,然后通过go mod tidy清理。

PS D:\go-demo> go get -u github.com/go-sql-driver/mysql
go: downloading github.com/go-sql-driver/mysql v1.8.1
go: downloading filippo.io/edwards25519 v1.1.0
go: added filippo.io/edwards25519 v1.1.0
go: added github.com/go-sql-driver/mysql v1.8.1

PS D:\go-demo> go mod tidy
go: downloading github.com/stretchr/testify v1.9.0
go: downloading gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405
go: downloading github.com/go-playground/assert/v2 v2.2.0
go: downloading github.com/davecgh/go-spew v1.1.1
go: downloading github.com/pmezard/go-difflib v1.0.0
go: downloading github.com/google/go-cmp v0.5.5
go: downloading golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543

  go mod tidy不仅对go.mod进行了清理,还分析各个源文件中的import,对直接依赖和间接依赖进行分离。如下:

  

  go mod tidy的详细使用可参见:https://www.51cto.com/article/777827.html。

2.5、go get和go install的区别

  有些包如gocov-html,go get和go install都可以安装,那他俩什么区别、什么时候应该用go get、什么时候应该用go install呢?

(一)命令定义和区别

go install 和 go get 都是 Go 语言的工具命令,但它们之间有一些区别。

  • go get:用于从远程代码存储库(如 GitHub)中下载或更新 Go 代码包。它会下载代码包并将其存储在 $GOPATH/src 目录下对应的位置,并编译代码包中的程序和库。如果目标包之前已经被下载过了,那么 go get 会尝试更新到最新版本,并重新编译程序和库文件。在更新完代码包后,go get 还会自动把下载的代码包的可执行文件复制到 $GOPATH/bin 目录下,以方便直接使用该可执行文件。

  • go install:用于编译并安装 Go 代码包,并将其生成的可执行程序或库文件存储到 $GOPATH/bin 或者 $GOPATH/pkg 目录下。如果你在项目目录下执行 go install,它将会编译并安装当前项目的代码,生成可执行文件并将其保存到 $GOPATH/bin 目录下(如果项目是一个库,则生成的是 .a 文件,并将其存储到 $GOPATH/pkg 目录下)。

因此,go get 用于下载和更新代码包,并产生对应的可执行程序,而 go install 用于将一个 Go 代码包转化为可执行程序或库文件,并安装到系统路径以供直接使用。

使用表格形式对 go get 和 go install 进行比较:

 

二)go get 是否包含了 go install

可以认为 go get 命令包含了 go install 命令的功能,但它们之间还是存在一些细微差别。

go get 命令用于从远程代码库中下载或更新 Go 代码包,并自动编译生成相应的可执行程序,同时还将其安装到 $GOPATH/bin 目录下,以便简化程序的运行。go get 命令不需要指定包的路径,它会使用 Go 语言规范中约定的包导入路径来获取包信息,并自动处理包的依赖关系以方便编译。

相比之下,go install 命令则更为灵活,它可以编译并安装当前项目的代码,生成可执行文件或库,并将其保存在 $GOPATH/bin 或 $GOPATH/pkg 目录下。同时,go install 命令还可以通过指定 -ldflags 参数来修改二进制文件的链接标志,从而将一些自定义的元信息加入到二进制文件中,使得可以在运行时通过代码读取这些信息。

在 Go 1.16 版本之后,go get 命令已经默认使用了 Go 模块管理工具。而 go install 命令则始终需要先进入到处于 Go 模块管理的路径下,然后才能使用该命令编译并安装相关代码包。

综上所述,可以认为 go get 命令包含了 go install 命令的部分功能,但是在一些特殊情况下,还是需要使用 go install 命令来进行更灵活的编译和安装操作。

(三)为什么要用 go install

在使用 go get 命令下载并安装代码包时,有些情况下生成的可执行文件可能无法生效,这通常是因为 Go 语言版本不兼容或编译环境不同导致的。而使用 go install 命令则可以避免这些问题,下面列举了几种常见情况:

  1. 版本不兼容:如果 go get 命令下载的代码包和当前使用的 Go 语言版本不兼容,那么 go get 命令可能会产生编译错误或生成无法运行的可执行文件。对于这种情况,使用 go install 命令可以保证使用的是当前系统上与 Go 语言版本兼容的编译器。

  2. 编译环境不同:在使用 go get 命令下载代码包时,有时它们的编译环境与当前环境不同,可能会导致可执行文件无法正常工作。而在使用 go install 命令时,该命令会在当前环境下重新编译源代码并生成可执行文件,从而能够更加稳定地运行代码。
  3. 依赖关系复杂:在使用 go get 命令下载大型的代码包时,它可能会自动下载和安装大量依赖项。这样可能会导致依赖关系变得复杂而难以管理,有时可能会在下载或编译依赖项时产生错误或警告。而 go install 命令会直接从当前路径下对应依赖项中寻找依赖项,因此可以避免这种情况下带来的复杂性和错误。

综上所述,尽管 go get 命令十分方便快捷,但在遇到一些特殊情况时,仍然需要使用 go install 命令以获得更加稳定的编译和安装效果。

可以使用如下表格来对比 go get 和 go install 的编译区别:

 

3、集成与调试

  虽然很多开发使用go build,但集成远不止go build和go install两个命令。

  其中build编译的时候最主要的是指定编译和链接两个选项。他们分别是 -gcflags和-ldflags。

-gcflags="pattern=arg list"

例如:go build -gcflags="all=-N -l" .

-ldflags 可以设置链接选项

-w 不生成 DWARF 调试信息(在c++中,g3和DWARF是debug的好能手)
-s 关闭符号表
-w 和 -s 通常一起使用,用来减少可执行文件的体积。但删除了调试信息后,可执行文件将无法使用 gdb/dlv 调试。

  更多可参见:https://studygolang.com/articles/22803和https://blog.csdn.net/cbmljs/article/details/128708627。

4、go语言的初始化顺序

5、性能分析(profiling)

6、测试用例和覆盖率

7、调用c共享库以及创建共享库供c/java调用

8、什么是goroutine?和线程的区别

9、gcc和go的版本对应关系 https://blog.csdn.net/flynetcn/article/details/131348741。

10、入门参考 

11、goyacc,基于go语言的解析器开发

  本质上和yacc高度雷同,可以参考goyacc的例子

参见:golang入门实践(vscode远程开发及调试配置、代码自动提示和跳转)

posted @   zhjh256  阅读(64)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
历史上的今天:
2024-01-10 postgresql distinct on用法
2024-01-10 postgresql 11开始支持sql:2011标准的所有window frame子句
点击右上角即可分享
微信分享提示