写在前面:这本书前前后后花了挺长时间,去年 11 月份就开始读了,中间又断了,直到最近才捡起来看完。
本书讲得内容非常全面,语言也很顺畅,生词非常少,并且内容没有太大难度,看起来比较过瘾,算是全面复习一下 Go 语言。如果你想开始练习阅读英文书,这本将是一个非常好的开始。
下面是阅读过程中记录的一些有用的点,随意看看就好。
go doc strings.Fields
获取库函数的解释;执行 go get golang.org/x/tools/cmd/godoc
会安装 godoc 工具,注意这两者是不同的。前者是 go 命令,后者则是 godoc 命令。执行 godoc -http :8080
可以启动一个 server,访问 http://localhost:8080/pkg/
即可看到 Go 的文档。go build
会显示生成一个可执行文件,仅仅一个 hello_world 就会达到 2M 大小,这是因为 Go 是静态链接,生成的文件可以直接执行,不需要再动态链接其他文件。而执行 go run
命令,虽然也会生成可执行文件,但是它是隐式的,之后当程序执行完后会被自动删掉。注意,看不见并不等于不存在!/dev/stdin
、/dev/stdout
、/dev/stderr
这三个特殊的文件名,它们也可以用 0、1、2 号文件描述符来描述。:=
不能用于函数之外,因此全局变量只能用 var
声明。func main() {
var f *os.File
f = os.Stdin
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
fmt.Println(">", scanner.Text())
}
}
按 ctrl+D 退出循环,因为 ctrl+D 会告知程序没有更多的数据可以读取。
os.Args
可以记录通过命令行输入的参数,并且它的类型是 []string,第一个元素是程序名,之后的为输入参数。例如:go run a.go 10 1
os.Args
为 [/tmp/go-build059507490/b001/exe/cla 10 1]
# 根据 tag 创建
docker build -t go_hw:v1 .
# 列出所有的 docker images
docker images
# 运行
docker run go_hw:v1
# 删除(-f 强制删除)
docker rmi 5a0d2473aa96 f56365ec0638
time go run xx.go
可以计算运行程序花费的时间。strace ls
查看都有哪些系统调用,-c
可以计数。# 两者等价
GOOS=darwin GOARCH=amd64 go tool compile -S goEnv.go
GOOS=darwin GOARCH=amd64 go build -gcflags -S goEnv.go
GOOS 和 GOARCH 可选项为:The list of valid GOOS values includes android, darwin, dragonfly, freebsd, linux, nacl, netbsd, openbsd, plan9, solaris, windows, and zos. On the other hand, the list of valid GOARCH values includes 386, amd64, amd64p32, arm, armbe, arm64, arm64be, ppc64, ppc64le, mips, mipsle, mips64, mips64le, mips64p32, mips64p32le, ppc, s390, s390x, sparc, and sparc64.
go build -x defer.go
展示 build 过程。math/rand
可用于生成伪随机数;更安全的生成随机数:crypto/rand
。...Type
称为 pack operator,而 Slice...
则被称为 unpack operator。一个可变参数的函数只能使用一次 pack operator。$ mkdir ~/go/src/aPackage
$ cp aPackage.go ~/go/src/aPackage/
$ go install aPackage
$ cd ~/go/pkg/darwin_amd64/
$ ls -l aPackage.a
-rw-r--r-- 1 mtsouk staff 4980 Dec 22 06:12 aPackage.a
编译一个本地包:
$ go tool compile aPackage.go
$ ls -l aPackage.*
-rw-r--r--@ 1 mtsouk staff 201 Jan 10 22:08 aPackage.go -rw-r--r-- 1 mtsouk staff 16316 Mar 4 20:01 aPackage.o
1
表示大版本,2
表示 feature,3
表示 fix。$ go mod init
go: creating new go.mod: module github.com/mactsouk/myModule
$ touch myModule.go
$ vi myModule.go
$ git add .
$ git commit -a -m "Initial version 1.0.0"
$ git push
$ git tag v1.0.0
$ git push -q origin v1.0.0
$ go list
github.com/mactsouk/myModule
$ go list -m
github.com/mactsouk/myModule
git commit -a -m "using v2.0.0"
git tag v2.0.0
git push --tags origin v2
git --no-pager branch -a
go mod init useV1V2
go mod vendor
grep \"syscall\" `find /usr/local/go/src -name "*.go"`
wc
命令的结果有三列,分别表示行数、word 数,以及字节数。平时用的最多的是 wc -l
,表示行数;wc -w
表示 wrod 数;wc -c
表示字节数。package main
import (
"fmt"
"os"
)
func main() {
arguments := os.Args
if len(arguments) == 1 {
fmt.Printf("usage: permissions filename\n")
return
}
filename := arguments[1]
info, _ := os.Stat(filename)
mode := info.Mode()
fmt.Println(filename, "mode is", mode.String()[1:10])
}
crtl+C
向进程发送 SIGINT 信号。Unix 里的信号其实都是软中断,用来异步处理“事件”,信号可以通过 name 和 number 来识别。进程不可能处理所有类型的信号,有些信号不能被 caught,不能被 blocked,例如 SIGKILL、SIGSTOP 不能被 caught,不能被 blocked,也不能被 ignored。因为它们给内核和 root 用户提供了特权,可以停止运行某些进程。一般我们建议用信号的 name 来操作,例如 kill -s INT pid
。有个例外的是 SIGKILL,它对应的 number 是 9,例如我们经常执行 kill -9 pid
来杀死某个进程,它等价于 kill -s KILL pid
。kill -l
命令可以列出所有支持的信号。go run -race xx.go
可以显示有竞争冲突的代码。diff pipeline.go plNoRace.go --color
显示两个文件的 diff。export GOMAXPROCS=800;
。time go run xx.go
可以显示执行时间,包括 real, sys, user 的执行时间。For garbage collection to work correctly, the parent goroutine needs to keep a reference to each child goroutine. If a child goroutine ends without the parent knowing about it, then a memory leak occurs until the parent is canceled as well.
"The real problem is that programmers have spent far too much time worrying about efficiency in the wrong places and at the wrong times; premature optimization is the root of all evil (or at least most of it) in programming."
告诉我们不要老想着性能优化,在真的出现问题、出现瓶颈的时候再来考虑。
还有 Erlang 的作者之一 Joe Armstrong:
"Make it work, then make it beautiful, then if you really, really have to, make it fast. 90 percent of the time, if you make it beautiful, it will already be fast. So really, just make it beautiful!"
这告诉我们性能优化并不是主要工作,我们不要花费大量精力在这上面。
env GOOS=linux GOARCH=386 go build xCompile.go
。指定操作系统、指令集。pkg/bytes
文档里有很多代码样例,还可以 run 一下,但其实这些样例是写死在源码里的,就在 src/bytes/example_test.go
文件里。一开始没发现这个文件,我直接拿样例代码全局搜,一下就找到了。例如,源码写的如下两个 example:// src
func ExampleToTitleSpecial() {
str := []byte("ahoj vývojári golang")
totitle := bytes.ToTitleSpecial(unicode.AzeriCase, str)
fmt.Println("Original : " + string(str))
fmt.Println("ToTitle : " + string(totitle))
// Output:
// Original : ahoj vývojári golang
// ToTitle : AHOJ VÝVOJÁRİ GOLANG
}
在 pkg[4] 上,就对应这样:
go pkg example
[1]这里: https://github.com/PacktPublishing/Mastering-Go-Second-Edition/blob/master/ch04/useStrings.go
[2]bytes 包: https://golang.org/pkg/bytes/
[3]源码: https://golang.org/src/bytes/bytes.go
[4]pkg: https://golang.org/pkg