【笔记】《Go并发编程实战》第二章 阅读笔记

2.2 工程结构

2.2.1 工作区

Go代码必须放在工作区中。工作区其实就是- -个对应 于特定工程的目录,它应包含3个子目录: src目录、 pkg目录和bin目录

src目录
用于以代码包的形式组织并保存Go源码文件。

pkg目录
pkg目录:用于存放经由go install命令构建安装后的代码包(包含Go库源码文件)的".a"归档文件。

bin目录
在通过go install命令完成安装后,保存由Go命令源码文件生成的可执行文件。

2.2.2 GOPATH

我们需要将工作区的目录路径添加至环境变量COPATH中。否则,即使处于同一工作区,代码之间也无法通过绝对代码包路径完成调用。在实际开发环境中,工作区往往有多个。这些工作区的目录路径都需要添加至GOPATH。

  • GOPATH中不要包含环境变量GOROOT的值(即Go的安装目录路径),以此将Go语言本身的工作区同用户工作区严格地分开。
  • 通过Go工具中的代码获取命令go get,可将指定项目的源码下载到我们在环境变量GOPATH中设定的第一个工作区中,并在其中完成构建和安装的过程。

2.2.3 源码文件

存储Go代码的文本文件需要以UTF-8编码存储。如果源码文件中出现了非UTF-8编码的字符,则在运行、编译或安装时,Go会抛出"illegal UTF-8 sequence"的错误。

命令源码文件

如果一个源码文件被声明为属于main代码包,且该文件代码中包含无参数声明和结果声明的main函数,则它就是命令源码文件。命令源码文件可通过go run命令直接启动运行。

同一个代码包中的所有源码文件,其所属代码包的名称必须一致。 如果命令源码文件和库源码文件处于同一一个代码包中,那么在该包中就无法正确执行go build和go install命令。换句话说,这些源码文件也就无法被编译和安装。因此,命令源码文件通常会单独放在一个代码包中。这是合理的,因为一般情况下, 一个程序模块或软件的启动入口只有一个。

同一个代码包中可以有多个命令源码文件,可通过go run命令分别运行它们。但这种情况会使go build和go install命 令无法编译和安装该代码包。所以一般情况下,也不建议把多个命令源码文件放在同一个代码包中。

当代码包中有且仅有一个命令源码文件时,在文件所在目录中执行go build命令,即可在该目录下生成一个与目录同名的可执行文件;而若使用go install命令,则可在当前工作区的bin目录下生成相应的可执行文件。

库源码文件

库源码文件声明的包名会与它实际所属的代码包(目录)名一致,且库源码文件中不包含无参数声明和无结果声明的main函数。

测试源码文件
测试源码文件是一种特殊的库文件, 可以通过执行go test命 令运行当前代码包下的所有测试源码文件。成为测试源码文件的充分条件有两个

  • 文件名需要以"_test.go" 结尾
  • 文件中需要至少包含一一个名称以"Test" 开头或"Benchmark"开头、拥有一个类型为"testing.T"或"testing.B" 的参数的函数。类型"testing.T" 和“esting.B" 分别对应功能测试和基准测试所需的结构体。

当我们在一个代码包中执行go test命令时,该代码包中的所有测试源码文件就会被找到并运行。

2.2.4 代码包

包声明

在Go语言中,代码包中的源码文件名可以是任意的,但这些任意名称的源码文件都必须以包声明语句package xxx作为文件中代码的第一行。

Go语言规定包声明中的包名为代码包路径的最后一个元素。比如,basic/set包的包路径为basic/set,而包声明中的包名则为set。但有一个例外,不论命令源码文件存放在哪个代码包中,它都必须声明为属于main包。

包导入

代码包的导入使用代码包导入路径。代码包导入路径就是代码包在工作区的src目录下的相对路径。

当导人多个代码包时,需要用圆括号括起它们,且每个代码包名独占一行。

在调用被导入代码包中的函数或使用其中的结构体、变量或常量时,需要使用包路径的最后一个元素加“.”的方式指定代码所在的包。

如果在同一个源码文件中导人多个代码包,那么代码包路径的最后一个元素不可以重复。否则会抛出"logging redeclared as imported package name"的错误。当有这类重复是,我们可以给它们起个别名来区分,如果别名为'.',则可以直接进行代码调用:

package main

import . "fmt"

func main() {
	var a,b int
	Scan(&a,&b)
	Println(a+b)
}

标识符的首字母的大小写控制着对应程序实体的访问权限。如果标识符的首字母是大写的.那么它所对应的程序实体就可以被本代码包之外的代码访问到,也可以称其为可导出的。否则,对应的程序实体就只能被本包内的代码访问。还有以下两个额外条件。

  • 程序实体必须是非局部的。局部程序实体的意思是,它被定义在了函数或结构体的内部。
  • 代码包所在的目录必须被包含在环境变量GOPATH中的工作区目录中。

回到代码包导人的问题上来。代码包导入还有另外-一种情况。如果我们只想初始化某个代码包而不需要在当前源码文件中使用那个代码包中的任何代码,就可以用"."来代替别名,如下所示:

import (
      _ "logging"
)

这种情况下,我们只触发了对代码包logging的初始化操作。

包初始化

在Go语言中,可以有专门的函数负责代码包初始化。这个函数需要无参数声明和结果声明,且名称必须为init,如下所示:

func init() {
      ...
}

在同一个代码包中,可以存在多个代码包初始化函数,甚至代码包内的每一一个源码文件都可以定义多个代码包初始化函数。Go语言编译器不能保证同一个代码包中的多个代码包初始化函数的执行顺序。如果确实要求按特定顺序执行的话,可以考虑使用Channel进行控制。

2.3 标准命令概述

build:  用于编译给定的代码包或Go语言源码文件及其依赖包。
clean:  用于清除执行其他go命令后遗留的目录和文件。
doc:  用于执行godoc命令以打印指定代码包。
env:  用于打印Go语言环境信息。
fix:  用于执行go tool fix命令以修正给定代码包的源码文件中包含的过时语法和代码调用。
fmt:  用于执行gofmt命令以格式化给定代码包中的源码文件。
get:  用于下载和安装给定代码包及其依赖包。
install:  用于编译和安装给定的代码包及其依赖包。
list:  用于显示给定代码包的信息。
run:  用于编译并运行给定的命令源码文件。
test:  用于测试给定的代码包。
tool:  用于运行Go语言的特殊工具。
version:  用于显示当前安装的Go语言的版本信息。

在执行这些命令的时候可以通过附加一些额外的标记来定制命令的执行过程。这些特殊参数可以添加到命令名称和命令的真正参数中间。用于构建、安装、运行和测试Go语言代码包或源码文件的命令都支持这些特殊参数。

-a:  用于强行重新构建所有涉及的Go语言代码包(包括Go语言标准库中的代码包),即使它们已经是最新的了。
-n:  使命令仅打印在执行期间使用到的所有命令,而不真正执行它们。
-v:  用于打印出命令执行过程中涉及的Go语言代码包的名字。这些代码包一般包括我们给定的目标代码包,有时还会包括该代码包直接或间接依赖的代码包。
-wrok:  打印出命令执行时生成和使用的临时工作目录的名字,且命令执行完成后不对它进行删除。
-x:  打印出命令执行期间使用到的所有命令。
posted @ 2020-06-08 20:36  Greenty  阅读(206)  评论(0编辑  收藏  举报