每天go一点点,只记录学习中, 自己用到和迷惑的东西, 记录精华部分, 不求大而全.
How to write go code(大白话译文)
网上很多译文, 但是写的都比较模糊, 大多都是直接翻译的, 这里我写上自己的理解, 使用大白话去解读. 英文名词我尽量不翻译. 因为-程序中都是英文.
介绍
这一部分 ①演示如何在一个module里面开发一个package. ②介绍常用的go tool, 它是用来 获取fetch/编译build/安装install modules, packages, commands的.
本文前提: Go 1.13以上版本, GO111MODULE环境变量没有设置.
如何组织代码
package
go程序是以package 包进行组织的, 一个package是指在同一文件夹下的go源文件.go的集合(也就是说, 同一文件夹下的go源文件, 必须同属一个package).
这些同一个文件夹下的go源文件是一起被编译的, 这也就导致任一源文件中定义的 函数/类型/变量/常量 都能直接被同属一个package的其他源文件引用.
repository/module/package的关系
一个repository 仓库可以包含一个/多个module, 一个module是相关的的package的集合. 通常一个repository只包含一个module(处于在repository的根目录, 即: 你会在repository的根目录发现一个go.mod文件).
module path的作用
go.mod文件, 声明了module path, 这个module path是该module下的所有的package的import path的前缀.
那么, 一个module包含哪些package呢? 答案是, go.mod文件的文件夹中的package, 以及该文件夹的子文件中的packages, 都是属于这个module的. (直到遇到一个子文件夹, 它拥有自己的go.mod文件, 此时就是另外一个module了.) 可以理解一个go.mod文件, 声明了一个module
上面说了, module path有一个作用是作为该module下面的packages的import path前缀. 其实它还有别的作用. **module path也指明了go 命令应该去哪里下载这个module. **
举例: 为了下载module path为golang.org/x/tools的module, go命令就会去访问仓库url: https://golang.org/x/tools.
import path
一个module下的package的import path的组成方式是:
module path/subdirectory path to the package
举例:
一个module的module path是 github.com/google/go-cmp, 在go-cmp/cmp/下, 有一个package, 则该packaeg的import path是: github.com/google/go-cmp/cmp.
这里有个例外, 就是标准库中的包, 都没有module path前缀, 如: import fmt.
第一个程序
创建module
首先, 自己想好一个module path, 并创建一个go.mod(创建一个module)
这里我们创建一个文件夹hello/, 在其下面创建一个module, modulepath为: example.com/user/hello
$ mkdir hello
$ cd hello
$ go mod init example.com/user/hello // module path
go: creating new go.mod: module example.com/user/hello
$ cat go.mod
module example.com/user/hello
为自己的module编写package
go源文件的第一条有效语句, 必须是package name, 可执行的module, 必须有package main.
在hello/下, 创建一个hello.go. 代码如下:
package main
import "fmt"
func main() {
fmt.Println("Hello, world.")
}
此时的目录结构如下:
.
└── hello
├── go.mod
└── hello.go
安装module
由于module包含了package main, 是可执行的, 那我们执行下面的语句, 编译并生成了hello可执行文件(命令).
// go install moduel_path
go install example.com/usr/hello
如果你没有设置$GOBIN, $GOPATH, 则编译生成的hello命令会被默认安装到$HOME/go/bin/hello(windows: %USERPROFILE%\go\bin\hello.exe).
可执行文件(命令)被安装到哪里, 是由$GOBIN > $GOPATH > 默认路径 决定的.
你可以通过如下命令, 设置/取消 go环境变量的设置
go env -w GOBIN=/somewhere/else/bin // 设置
go env -u GOBIN // 取消
注意:go install module_path命令执行的时候, 必须在相应的module的范围内, 不能在module范围之外的地方通过go install module_path安装相应的module.
如果module path没有在go命令中给出, go命令是可以接收相对路径的(相对当前工作目录), 但是此时go命令的作用对象默认是当前工作目录的package.
如, 在当前的目录下, 以下语句的效果是等价的
// 安装module example.com/usr/hello
go install example.com/usr/hello
// 以下两条命令, 安装当前目录下的pacakge hello
go install .
go install
repository 和 module path
如果你已经提交你的repository到github, 为了方便别人去使用你的repository, 那么你的仓库的地址和你的module path最好是一致的.
如何引用自己module中的package
在你自己的moudle中, 创建一个新的package
新建一个package morestrings, 为其创建一个目录hello/morestrings/目录结构如下:
.
└── hello
├── go.mod
├── hello.go
└── morestrings //package morestrings所在的文件夹
└── reverse.go
reverse.go代码如下: 注意函数名是大写开头, 表示可导出的.
package morestrings
// 反转字符串
func ReverseRunes(s string) string {
r := []rune(s)
for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
r[i], r[j] = r[j], r[i]
}
return string(r)
}
我们使用go build去编译package morestrings.
cd hello/morestrings/
go build
这个命令不会有任何输出, 其实它是将编译后的package内容放到了本地的编译缓存中.
引入刚才创建的morestrings包
修改hello.go文件:
package main
import (
"fmt"
"example.com/user/hello/morestrings" // package morestrings的import path
)
func main() {
fmt.Println(morestrings.ReverseRunes("!oG ,olleH"))
}
安装module hello: go install example.com/usr/hello,
引入远端的module中的包
package的import path描述了如何去获取该pacakge的源代码.
比如: 为了使用 github.com/google/go-cmp/cmp包
package main
import (
"fmt"
"example.com/user/hello/morestrings"
"github.com/google/go-cmp/cmp" // 引入外部包
)
func main() {
fmt.Println(morestrings.ReverseRunes("!oG ,olleH"))
fmt.Println(cmp.Diff("Hello World", "Hello Go"))
}
当你运行go install, go build, go run等命令的时候, go命令会自动的下载你要导入的package所属的module的源代码. 并将该module的版本记录在go.mod文件中.
$ go install example.com/user/hello
go: finding module for package github.com/google/go-cmp/cmp
go: downloading github.com/google/go-cmp v0.4.0
go: found github.com/google/go-cmp/cmp in github.com/google/go-cmp v0.4.0
$ cat go.mod
module example.com/user/hello
go 1.14
require github.com/google/go-cmp v0.4.0
$
依赖的module下载后, 会放到$GOPAHT/pkg/mod/文件夹下. 该module可以被其他的moduel共享使用(版本必须相同).