转载

Go核心36讲笔记

Part1

.GO 语言安装的时候主要有三个环境变量:

GOROOT、GOPATH 和 GOBIN

通过 go env 可以查看go语言的一系列的环境变量的配置.

go env
GOROOT :代表go的安装路径,一般你安装完go语言之后就有了。

GOPATH :一个目录路径,也可以包含多个目录路径,每个目录都代表了go语言的一个“工作区”。目录下面有三个目录,src,bin,pkg。

src : 用来存放源代码文件。

bin : 目录里面存放的都是通过 go install 命令安装后,由 Go 命令源码文件生成的可执行文件。

有两种情况下,bin 目录会变得没有意义。

当设置了有效的 GOBIN 环境变量以后,bin 目录就变得没有意义。

如果 GOPATH 里面包含多个工作区路径的时候,必须设置 GOBIN 环境变量,否则就无法安装 Go 程序的可执行文件。

pkg:用来存放通过 go install 命令安装后的代码包的归档文件(.a 文件)

GOBIN:存放可执行文件的文件目录。

Go 的源码文件分类:

(1)命令源码文件:

声明自己属于 main 代码包、包含无参数声明和结果声明的 main 函数。
    命令源码文件被安装以后,GOPATH 如果只有一个工作区,那么相应的
    可执行文件会被存放当前工作区的 bin 文件夹下;如果有多个工作区,
    就会安装到 GOBIN 指向的目录下。

(2)库源码文件

库源码文件就是不具备命令源码文件上述两个特征的源码文件。存在于某个代码包中的普通的源码文件。

(3)测试源码文件

名称以 _test.go 为后缀的代码文件,并且必须包含 Test 或者 Benchmark 名称前缀的函数。

详情可以参照

理解内容:

  1. pkg 目录是用来存放通过 go install 命令安装后的代码包的归档文件(.a 文件)。归档文件的名字就是代码包的名字。所有归档文件都会被存放到该目录下的平台相关目录中,即在 $GOPATH/pkg/$GOOS_$GOARCH 中,同样以代码包为组织形式。同时这里有两个隐藏的环境变量, GOOSGOARCH 。这两个环境变量是不用我们设置的,系统就默认的。 GOOS 是 Go 所在的操作系统类型, GOARCH 是 Go 所在的计算架构。平台相关目录是以 $GOOS_$GOARCH 命名的,Mac 平台上这个目录名就是 darwin_amd64。
  2. 命令源码文件并不一定必须放在 src 文件夹中的。
    这里需要纠正一个错误的观点:“所有的 Go 的代码都要放在 GOPATH 目录下”(这个观点是错误的)
    Go核心36讲笔记

    go源码文件

    其中go源码文件包含以下三种:
  • 命令源码文件:声明自己属于 main 代码包、包含无参数声明和结果声明的 main 函数。----main包
    两个main包的go文件可以单独go run运行, 但是不能go build 运行,因为go run时只运行当前文件,go build会编译当前包内所有文件。所以 go install 也不可以。
  • 库源码文件:库源码文件就是不具备命令源码文件上述两个特征的源码文件。存在于某个代码包中的普通的源码文件。库源码文件被安装后,相应的归档文件(.a 文件)会被存放到当前工作区的 pkg 的平台相关目录下。
  • 测试源码文件
    名称以 _test.go 为后缀的代码文件,并且必须包含 Test 或者 Benchmark 名称前缀的函数。
func TestXXX( t *testing.T) {

}

名称以 Test 为名称前缀的函数,只能接受 *testing.T 的参数,这种测试函数是功能测试函数。

func BenchmarkXXX( b *testing.B) {

}

名称以 Benchmark 为名称前缀的函数,只能接受 *testing.B 的参数,这种测试函数是性能测试函数。

因此:命令源码文件是可以单独运行的。可以使用 go run 命令直接运行,也可以通过 go build 或 go install 命令得到相应的可执行文件。所以命令源码文件是可以在机器的任何目录下运行的。

包名 main 则告诉我们它是一个可独立运行的包,它在编译后会产生可执行文件。除了 main 包之外,其它的包最后都会生成 *.a 文件(也就是包文件)并放置在 $GOPATH/pkg/$GOOS_$GOARCH 中(以 Mac 为例就是 $GOPATH/pkg/darwin_amd64 )。

go run

Go核心36讲笔记

image

中间产生两个临时文件。

go build

go build 用于编译我们指定的源码文件或代码包以及它们的依赖包。,但是注意如果用来编译非命令源码文件,即库源码文件,go build 执行完是不会产生任何结果的。这种情况下,go build 命令只是检查库源码文件的有效性,只会做检查性的编译,而不会输出任何结果文件。

go build 编译命令源码文件,则会在该命令的执行目录中生成一个可执行文件

go run 和go build的前几步都一样,只是最后go run 执行可执行文件,go build 不执行。

  • 如果构建的是库源码文件,那么操作的结果文件只会存在于临时目录中。这里的构建的主要意义在于检查和验证。也就是构建了临时目录,然后就丢弃了。如果有问题就会报出来,如果没问题就相当于一顿操作后什么都没变化,就是上面说的加和验证。
  • 如果构建的是命令源码文件,那么操作的结果文件会被搬运到那个源码文件所在的目录中。一般构建就是用来做这个事情的。
Go核心36讲笔记

image

go install

go install 命令是用来编译并安装代码包或者源码文件的。

安装操作会先执行构建,然后还会进行链接操作,并且把结果文件搬运到指定目录。

前面几步依旧和 go run 、go build 完全一致,只是最后一步的差别,go install 会把命令源码文件安装到当前工作区的 bin 目录(如果 GOPATH 下有多个工作区,就会放在 GOBIN 目录下)。如果是库源码文件,就会被安装到当前工作区的 pkg 的平台相关目录下。

例如:go install github.com/labstack/echo

  • 如果是命令源码文件会安装在当前工作区GOPATH的bin下echo的可执行文件。
  • 如果是库源码文件则安装到当前工作区GOPATH/pkg/当前平台/github.com/labstack/echo.a 文件。
Go核心36讲笔记

image

go install 命令不支持针对库源码文件的安装操作。

go get

go get 命令会把当前的代码包下载到 $GOPATH 中的第一个工作区的 src 目录中,并安装。

如果在 go get 下载过程中加入-d 标记,那么下载操作只会执行下载动作,而不执行安装动作。

-u标记,加上它可以利用网络来更新已有的代码包及其依赖包。

Go核心36讲笔记

image

小结

  • 命令源码文件,通过构建或安装都可以完成编译,只是生成的可执行文件的目录不同。一般就用构建了,可以带参数指定位置。
  • 库源码文件,只有通过安装才能在pkg中生成包文件。
  • 一般就是构建源码文件。库文件的话就是进行安装。

问题

  1. Go 语言在多个工作区中查找依赖包的时候是以怎样的顺序进行的?
  • 如果有多个工作区,那么是按照GOPATH里面的先后顺序查找的
  1. 如果在多个工作区中都存在导入路径相同的代码包会产生冲突吗?
  • 不会冲突,像上面说的会按照顺序查找执行
  1. 如果我的src下面的文件夹名字叫做hello,但package的名字叫做HelloGO
package HelloGo

import "fmt"

func PrintHello(){
    fmt.Println("Hello Go")
}

这时候如果你想调用这个包,代码应该怎么写,

import HelloGo?
    还是import hello

答案肯定是import hello的,因为GOPATH的特性,只会按照目录来查找包,但你调用的时候就不能用目录名字来调用了:

package main

import "fmt"
import "hello"

func main() {
    fmt.Println("Hello, world!")
    HelloGo.PrintHello() //导入包的时候用文件夹名字,调用函数用package的名字
}

go build 命令

在运行go build命令的时候,默认不会编译目标代码包所依赖的那些代码包,如果归档文件已经存在的话。如果被依赖的代码包的归档文件不存在,或者源码文件有了变化,那它还是会被编译。常用参数说明:

-a : 可以强制编译依赖的代码包

-i : 不但要编译依赖的代码包,还要安装它们的归档文件

-x : 查看go build命令具体执行了哪些操作

-n : 同上,只查看操作,但是不实际执行

-v : 可以看到go build命令编译的代码包的名称。搭配-a参数使用时很有用

go get 命令

命令go get会自动下载代码包,并把它们安装到环境变量GOPATH包含的第1工作区的相应目录中。如果存在环境变量GOBIN,那么仅包含命令源码文件的代码包会被安装到GOBIN指向的那个目录。常用参数说明:

-u : 下载并安装代码包,不论是否已存在

-d : 只下载代码包,不安装代码包

-fix : 在下载代码包后先运行一个用于根据当前Go语言版本修正代码的工具,然后再安装代码包

-t : 同时下载测试所需的代码包

-insecure : 允许通过非安全的网络协议下载和安装代码包。比如:HTTP。

自定义代码包远程导入路径

如果你想把你编写的(被托管在不同的代码托管网站上的)代码包的远程导入路径统一起来,或者不希望让你的代码包中夹杂某个代码托管网站的域名,那么你可以选择自定义你的代码包远程导入路径。这种自定义的实现手段叫做“导入注释”。

比如代码实际存储的位置是:github.com/golang/sync/

但是安装的时候实际使用的命令是:go get golang.org/x/sync。这里就隐藏了github.com的域名,以及后面的部分路径golang。

导入注释

导入注释必须出现在源码文件的代码包声明语句的右边,是一条单行注释。被双引号包裹的是一个符合导入路径语法规则的字符串。下面是 github.com/golang/sync 下 semaphore/semaphore.go 里的导入注释:

package semaphore // import “golang.org/x/sync/semaphore”

这样加入导入注释后,就无法用github的地址来下载这个包了。但是也无法用自定义的路径来下载这个包,应该自定义的路径的网址还不能响应这个请求

编写网站的处理请求

编写一个可处理HTTP请求的程序。将对这个url响应的请求头中加入如下的一行内容:

这行内容会被视为HTML文档的元数据。这个就是go get命令的文档中要求的写法。它的模式是这样的:

content属性中的import-prefix的位置上填入自定义的远程代码包导入路径的前缀。而vsc代表与版本控制系统有关的标识,比如git。至于repo-root,它应该是与该处理程序关联的路径对应的Github网站的URL,即实际网址。

这么做的好处是,可以强化你的品牌,而不是某个代码托管网站的。顺便还可以隐藏掉用户ID,也就是域名后的部分路径。

最主要的是,使你的代码包导入路径整齐划一,如果代码包分散在不同的远程路径的话。

欢迎关注我们的微信公众号,每天学习Go知识

Go核心36讲笔记
原文  https://studygolang.com/articles/29600
正文到此结束
Loading...