This commit is contained in:
Xargin 2016-10-10 15:17:50 +08:00
parent ef1d302ae6
commit 1a5593ac1c
9 changed files with 21 additions and 21 deletions

View File

@ -21,6 +21,6 @@ func main() {
关于默认包名一般采用导入路径名的最后一段的约定也有三种例外情况。第一个例外包对应一个可执行程序也就是main包这时候main包本身的导入路径是无关紧要的。名字为main的包是给go build§10.7.3)构建命令一个信息,这个包编译完之后必须调用连接器生成一个可执行程序。 关于默认包名一般采用导入路径名的最后一段的约定也有三种例外情况。第一个例外包对应一个可执行程序也就是main包这时候main包本身的导入路径是无关紧要的。名字为main的包是给go build§10.7.3)构建命令一个信息,这个包编译完之后必须调用连接器生成一个可执行程序。
第二个例外,包所在的目录中可能有一些文件名是以``_test.go``为后缀的Go源文件译注前面必须有其它的字符因为以``_``前缀的源文件是被忽略的并且这些源文件声明的包名也是以_test为后缀名的。这种目录可以包含两种包一种普通包加一种则是测试的外部扩展包。所有以_test为后缀包名的测试外部扩展包都由go test命令独立编译普通包和测试的外部扩展包是相互独立的。测试的外部扩展包一般用来避免测试代码中的循环导入依赖具体细节我们将在11.2.4节中介绍。 第二个例外,包所在的目录中可能有一些文件名是以``_test.go``为后缀的Go源文件译注前面必须有其它的字符因为以`_`或`.`开头的源文件会被构建工具忽略),并且这些源文件声明的包名也是以`_test`为后缀名的。这种目录可以包含两种包:一种是普通包,另一种则是测试的外部扩展包。所有以`_test`为后缀包名的测试外部扩展包都由go test命令独立编译普通包和测试的外部扩展包是相互独立的。测试的外部扩展包一般用来避免测试代码中的循环导入依赖具体细节我们将在11.2.4节中介绍。
第三个例外,一些依赖版本号的管理工具会在导入路径后追加版本号信息,例如"gopkg.in/yaml.v2"。这种情况下包的名字并不包含版本号后缀而是yaml。 第三个例外,一些依赖版本号的管理工具会在导入路径后追加版本号信息,例如"gopkg.in/yaml.v2"。这种情况下包的名字并不包含版本号后缀而是yaml。

View File

@ -30,7 +30,7 @@ type Reader struct{ /* ... */ }
func NewReader(s string) *Reader func NewReader(s string) *Reader
``` ```
字符串string本身并没有出现在每个成员名字中。因为用户会这样引用这些成员strings.Index、strings.Replacer等。 包名strings并没有出现在任何成员名字中。因为用户会这样引用这些成员strings.Index、strings.Replacer等。
其它一些包可能只描述了单一的数据类型例如html/template和math/rand等只暴露一个主要的数据结构和与它相关的方法还有一个以New命名的函数用于创建实例。 其它一些包可能只描述了单一的数据类型例如html/template和math/rand等只暴露一个主要的数据结构和与它相关的方法还有一个以New命名的函数用于创建实例。

View File

@ -38,7 +38,7 @@ GOPATH对应的工作区目录有三个子目录。其中src子目录用于存
第二个环境变量GOROOT用来指定Go的安装目录还有它自带的标准库包的位置。GOROOT的目录结构和GOPATH类似因此存放fmt包的源代码对应目录应该为$GOROOT/src/fmt。用户一般不需要设置GOROOT默认情况下Go语言安装工具会将其设置为安装的目录路径。 第二个环境变量GOROOT用来指定Go的安装目录还有它自带的标准库包的位置。GOROOT的目录结构和GOPATH类似因此存放fmt包的源代码对应目录应该为$GOROOT/src/fmt。用户一般不需要设置GOROOT默认情况下Go语言安装工具会将其设置为安装的目录路径。
其中`go env`命令用于查看Go语言工具涉及的所有环境变量的值包括未设置环境变量的默认值。GOOS环境变量用于指定目标操作系统例如android、linux、darwin或windowsGOARCH环境变量用于指定处理器的类型例如amd64、386或arm等。虽然GOPATH环境变量是唯一必要设置的,但是其它环境变量也会偶尔用到。 其中`go env`命令用于查看Go语言工具涉及的所有环境变量的值包括未设置环境变量的默认值。GOOS环境变量用于指定目标操作系统例如android、linux、darwin或windowsGOARCH环境变量用于指定处理器的类型例如amd64、386或arm等。虽然GOPATH环境变量是唯一必要设置的,但是其它环境变量也会偶尔用到。
``` ```
$ go env $ go env

View File

@ -33,9 +33,9 @@ $ ./fetch https://golang.org/x/net/html | grep go-import
content="golang.org/x/net git https://go.googlesource.com/net"> content="golang.org/x/net git https://go.googlesource.com/net">
``` ```
如果指定`-u`命令行标志参数,`go get`命令将确保所有的包和依赖的包的版本都是最新的,然后重新编译和安装它们。如果不包含该标志参数的话,而且如果包已经在本地存在,那么代码那么将不会被自动更新。 如果指定`-u`命令行标志参数,`go get`命令将确保所有的包和依赖的包的版本都是最新的,然后重新编译和安装它们。如果不包含该标志参数的话,而且如果包已经在本地存在,那么代码将不会被自动更新。
`go get -u`命令只是简单地保证每个包是最新版本,如果是第一次下载包则是比较方便的但是对于发布程序则可能是不合适的因为本地程序可能需要对依赖的包做精确的版本依赖管理。通常的解决方案是使用vendor的目录用于存储依赖包的固定版本的源代码对本地依赖的包的版本更新也是谨慎和持续可控的。在Go1.5之前一般需要修改包的导入路径所以复制后golang.org/x/net/html导入路径可能会变为gopl.io/vendor/golang.org/x/net/html。最新的Go语言命令已经支持vendor特性但限于篇幅这里并不讨论vendor的具体细节。不过可以通过`go help gopath`命令查看Vendor的帮助文档。 `go get -u`命令只是简单地保证每个包是最新版本如果是第一次下载包则是比较方便的但是对于发布程序则可能是不合适的因为本地程序可能需要对依赖的包做精确的版本依赖管理。通常的解决方案是使用vendor的目录用于存储依赖包的固定版本的源代码对本地依赖的包的版本更新也是谨慎和持续可控的。在Go1.5之前一般需要修改包的导入路径所以复制后golang.org/x/net/html导入路径可能会变为gopl.io/vendor/golang.org/x/net/html。最新的Go语言命令已经支持vendor特性但限于篇幅这里并不讨论vendor的具体细节。不过可以通过`go help gopath`命令查看Vendor的帮助文档。
(译注墙内用户在上面这些命令的基础上还需要学习用翻墙来go get。) (译注墙内用户在上面这些命令的基础上还需要学习用翻墙来go get。)

View File

@ -1,10 +1,10 @@
### 10.7.3. 构建包 ### 10.7.3. 构建包
`go build`命令编译命令行参数指定的每个包。如果包是一个库,则忽略输出结果;这可以用于检测包的可以正确编译的。如果包的名字是main`go build`将调用连接器在当前目录创建一个可执行程序;以导入路径的最后一段作为可执行程序的名字。 `go build`命令编译命令行参数指定的每个包。如果包是一个库,则忽略输出结果;这可以用于检测包是可以正确编译的。如果包的名字是main`go build`将调用链接器在当前目录创建一个可执行程序;以导入路径的最后一段作为可执行程序的名字。
因为每个目录只包含一个包因此每个对应可执行程序或者叫Unix术语中的命令的包会要求放到一个独立的目录中。这些目录有时候会放在名叫cmd目录的子目录下面例如用于提供Go文档服务的golang.org/x/tools/cmd/godoc命令就是放在cmd子目录§10.7.4)。 由于每个目录只包含一个包因此每个对应可执行程序或者叫Unix术语中的命令的包会要求放到一个独立的目录中。这些目录有时候会放在名叫cmd目录的子目录下面例如用于提供Go文档服务的golang.org/x/tools/cmd/godoc命令就是放在cmd子目录§10.7.4)。
每个包可以由它们的导入路径指定,就像前面看到的那样,或者用一个相对目录的路径指定,相对路径必须以`.`或`..`开头。如果没有指定参数,那么默认指定为当前目录对应的包。 下面的命令用于构建同一个包, 虽然它们的写法各不相同: 每个包可以由它们的导入路径指定,就像前面看到的那样,或者用一个相对目录的路径指定,相对路径必须以`.`或`..`开头。如果没有指定参数,那么默认指定为当前目录对应的包。 下面的命令用于构建同一个包, 虽然它们的写法各不相同:
``` ```
$ cd $GOPATH/src/gopl.io/ch1/helloworld $ cd $GOPATH/src/gopl.io/ch1/helloworld
@ -33,7 +33,7 @@ $ go build src/gopl.io/ch1/helloworld
Error: cannot find package "src/gopl.io/ch1/helloworld". Error: cannot find package "src/gopl.io/ch1/helloworld".
``` ```
也可以指定包的源文件列表,这一般只用于构建一些小程序或做一些临时性的实验。如果是main包将会以第一个Go源文件的基础文件名作为最终的可执行程序的名字。 也可以指定包的源文件列表这一般只用于构建一些小程序或做一些临时性的实验。如果是main包将会以第一个Go源文件的基础文件名作为最终的可执行程序的名字。
``` ```
$ cat quoteargs.go $ cat quoteargs.go
@ -88,7 +88,7 @@ $ ./cross
darwin 386 darwin 386
``` ```
有些包可能需要针对不同平台和处理器类型使用不同版本的代码文件,以便于处理底层的可移植性问题或提供为一些特定代码提供优化。如果一个文件名包含了一个操作系统或处理器类型名字例如net_linux.go或asm_amd64.sGo语言的构建工具将只在对应的平台编译这些文件。还有一个特别的构建注释注释可以提供更多的构建过程控制。例如,文件中可能包含下面的注释: 有些包可能需要针对不同平台和处理器类型使用不同版本的代码文件以便于处理底层的可移植性问题或为一些特定代码提供优化。如果一个文件名包含了一个操作系统或处理器类型名字例如net_linux.go或asm_amd64.sGo语言的构建工具将只在对应的平台编译这些文件。还有一个特别的构建注释参数可以提供更多的构建过程控制。例如,文件中可能包含下面的注释:
```Go ```Go
// +build linux darwin // +build linux darwin

View File

@ -2,7 +2,7 @@
Go语言的编码风格鼓励为每个包提供良好的文档。包中每个导出的成员和包声明前都应该包含目的和用法说明的注释。 Go语言的编码风格鼓励为每个包提供良好的文档。包中每个导出的成员和包声明前都应该包含目的和用法说明的注释。
Go语言中包文档注释一般是完整的句子,第一行是包的摘要说明,注释后仅跟着包声明语句。注释中函数的参数或其它的标识符并不需要额外的引号或其它标记注明。例如下面是fmt.Fprintf的文档注释。 Go语言中的文档注释一般是完整的句子,第一行通常是摘要说明,以被注释者的名字开头。注释中函数的参数或其它的标识符并不需要额外的引号或其它标记注明。例如下面是fmt.Fprintf的文档注释。
```Go ```Go
// Fprintf formats according to a format specifier and writes to w. // Fprintf formats according to a format specifier and writes to w.
@ -16,7 +16,7 @@ Fprintf函数格式化的细节在fmt包文档中描述。如果注释后仅跟
在本书中,只要空间允许,我们之前很多包声明都包含了注释文档,但你可以从标准库中发现很多更好的例子。有两个工具可以帮到你。 在本书中,只要空间允许,我们之前很多包声明都包含了注释文档,但你可以从标准库中发现很多更好的例子。有两个工具可以帮到你。
首先是`go doc`命令,该命令打印包的声明和每个成员的文档注释,下面是整个包的文档 首先是`go doc`命令,该命令打印其后所指定的实体的声明与文档注释,该实体可能是一个包
``` ```
$ go doc time $ go doc time
@ -34,7 +34,7 @@ type Time struct { ... }
...many more... ...many more...
``` ```
或者是某个具体包成员的注释文档 或者是某个具体包成员:
``` ```
$ go doc time.Since $ go doc time.Since
@ -44,7 +44,7 @@ func Since(t Time) Duration
It is shorthand for time.Now().Sub(t). It is shorthand for time.Now().Sub(t).
``` ```
或者是某个具体包的一个方法的注释文档 或者是一个方法:
``` ```
$ go doc time.Duration.Seconds $ go doc time.Duration.Seconds
@ -63,7 +63,7 @@ func (dec *Decoder) Decode(v interface{}) error
it in the value pointed to by v. it in the value pointed to by v.
``` ```
第二个工具名字也叫godoc它提供可以相互交叉引用的HTML页面但是包含和`go doc`命令相同以及更多的信息。10.1演示了time包的文档11.6节将看到godoc演示可以交互的示例程序。godoc的在线服务 https://godoc.org ,包含了成千上万的开源包的检索工具。 第二个工具名字也叫godoc它提供可以相互交叉引用的HTML页面但是包含和`go doc`命令相同以及更多的信息。10.1演示了time包的文档11.6节将看到godoc演示可以交互的示例程序。godoc的在线服务 https://godoc.org ,包含了成千上万的开源包的检索工具。
你也可以在自己的工作区目录运行godoc服务。运行下面的命令然后在浏览器查看 http://localhost:8000/pkg 页面: 你也可以在自己的工作区目录运行godoc服务。运行下面的命令然后在浏览器查看 http://localhost:8000/pkg 页面:

View File

@ -1,8 +1,8 @@
### 10.7.5. 内部包 ### 10.7.5. 内部包
在Go语言程序中包的封装机制是一个重要的特性。没有导出的标识符只在同一个包内部可以访问,而导出的标识符则是面向全宇宙都是可见的。 在Go语言程序中是最重要的封装机制。没有导出的标识符只在同一个包内部可以访问,而导出的标识符则是面向全宇宙都是可见的。
有时候,一个中间的状态可能也是有用的,对于一小部分信任的包是可见的,但并不是对所有调用者都可见。例如,当我们计划将一个大的包拆分为很多小的更容易维护的子包,但是我们并不想将内部的子包结构也完全暴露出去。同时,我们可能还希望在内部子包之间共享一些通用的处理包,或者我们只是想实验一个新包的还并不稳定的接口,暂时只暴露给一些受限制的用户使用。 有时候,一个中间的状态可能也是有用的,标识符对于一小部分信任的包是可见的,但并不是对所有调用者都可见。例如,当我们计划将一个大的包拆分为很多小的更容易维护的子包,但是我们并不想将内部的子包结构也完全暴露出去。同时,我们可能还希望在内部子包之间共享一些通用的处理包,或者我们只是想实验一个新包的还并不稳定的接口,暂时只暴露给一些受限制的用户使用。
![](../images/ch10-01.png) ![](../images/ch10-01.png)

View File

@ -7,7 +7,7 @@ $ go list github.com/go-sql-driver/mysql
github.com/go-sql-driver/mysql github.com/go-sql-driver/mysql
``` ```
`go list`命令的参数还可以用`"..."`表示匹配任意的包的导入路径。我们可以用它来列工作区中的所有包: `go list`命令的参数还可以用`"..."`表示匹配任意的包的导入路径。我们可以用它来列工作区中的所有包:
``` ```
$ go list ... $ go list ...
@ -113,4 +113,4 @@ $ go list -f "{{.ImportPath}} -> {{join .Imports \" \"}}" compress/...
在本章我们解释了Go语言工具中除了测试命令之外的所有重要的子命令。在下一章我们将看到如何用`go test`命令去运行Go语言程序中的测试代码。 在本章我们解释了Go语言工具中除了测试命令之外的所有重要的子命令。在下一章我们将看到如何用`go test`命令去运行Go语言程序中的测试代码。
**练习 10.4** 创建一个工具,根据命令行指定的参数,报告工作区所有依赖指定的其它包集合。提示:你需要运行`go list`命令两次一次用于初始化包一次用于所有包。你可能需要用encoding/json§4.5包来分析输出的JSON格式的信息。 **练习 10.4** 创建一个工具,根据命令行指定的参数,报告工作区所有依赖指定的其它包集合。提示:你需要运行`go list`命令两次一次用于初始化包一次用于所有包。你可能需要用encoding/json§4.5包来分析输出的JSON格式的信息。

View File

@ -2,7 +2,7 @@
本章剩下的部分将讨论Go语言工具箱的具体功能包括如何下载、格式化、构建、测试和安装Go语言编写的程序。 本章剩下的部分将讨论Go语言工具箱的具体功能包括如何下载、格式化、构建、测试和安装Go语言编写的程序。
Go语言的工具箱集合了一系列的功能的命令集。它可以看作是一个包管理器类似于Linux中的apt和rpm工具用于包的查询、计算包依赖关系、从远程版本控制系统下载它们等任务。它也是一个构建系统,计算文件的依赖关系,然后调用编译器、汇编器和接器构建程序虽然它故意被设计成没有标准的make命令那么复杂。它也是一个单元测试和基准测试的驱动程序我们将在第11章讨论测试话题。 Go语言的工具箱集合了一系列的功能的命令集。它可以看作是一个包管理器类似于Linux中的apt和rpm工具用于包的查询、计算包依赖关系、从远程版本控制系统下载它们等任务。它也是一个构建系统,计算文件的依赖关系,然后调用编译器、汇编器和接器构建程序虽然它故意被设计成没有标准的make命令那么复杂。它也是一个单元测试和基准测试的驱动程序我们将在第11章讨论测试话题。
Go语言工具箱的命令有着类似“瑞士军刀”的风格带着一打子的子命令有一些我们经常用到例如get、run、build和fmt等。你可以运行go或go help命令查看内置的帮助文档为了查询方便我们列出了最常用的命令 Go语言工具箱的命令有着类似“瑞士军刀”的风格带着一打子的子命令有一些我们经常用到例如get、run、build和fmt等。你可以运行go或go help命令查看内置的帮助文档为了查询方便我们列出了最常用的命令
@ -26,7 +26,7 @@ Use "go help [command]" for more information about a command.
... ...
``` ```
为了达到零配置的设计目标Go语言的工具箱很多地方都依赖各种约定。例如根据给定的源文件的名称Go语言的工具可以找到源文件对应的包因为每个目录只包含了单一的包并且的导入路径和工作区的目录结构是对应的。给定一个包的导入路径Go语言的工具可以找到对应的目录中没个实体对应的源文件。它还可以根据导入路径找到存储代码仓库的远程服务器的URL。 为了达到零配置的设计目标Go语言的工具箱很多地方都依赖各种约定。例如根据给定的源文件的名称Go语言的工具可以找到源文件对应的包因为每个目录只包含了单一的包并且的导入路径和工作区的目录结构是对应的。给定一个包的导入路径Go语言的工具可以找到与之对应的存储着实体文件的目录。它还可以根据导入路径找到存储代码仓库的远程服务器的URL。
{% include "./ch10-07-1.md" %} {% include "./ch10-07-1.md" %}