写在前面:这本书前前后后花了挺长时间,去年 11 月份就开始读了,中间又断了,直到最近才捡起来看完。

本书讲得内容非常全面,语言也很顺畅,生词非常少,并且内容没有太大难度,看起来比较过瘾,算是全面复习一下 Go 语言。如果你想开始练习阅读英文书,这本将是一个非常好的开始。

下面是阅读过程中记录的一些有用的点,随意看看就好。


  1. Go 有很多优点,其中一点是没有预编译阶段,这使得它的编译速度更快。像 C 语中,以 # 开头的会被预编译器处理。有预编译器的语言有:C, C++, Ada, and PL/SQL。预编译器的一大缺点是它会修改源代码,而人们不知道送到编译器里的最终的代码是什么。

  2. 可以直接在命令行执行 go doc strings.Fields 获取库函数的解释;执行 go get golang.org/x/tools/cmd/godoc 会安装 godoc 工具,注意这两者是不同的。前者是 go 命令,后者则是 godoc 命令。执行 godoc -http :8080 可以启动一个 server,访问 http://localhost:8080/pkg/ 即可看到 Go 的文档。

  3. 执行 go build 会显示生成一个可执行文件,仅仅一个 hello_world 就会达到 2M 大小,这是因为 Go 是静态链接,生成的文件可以直接执行,不需要再动态链接其他文件。而执行 go run 命令,虽然也会生成可执行文件,但是它是隐式的,之后当程序执行完后会被自动删掉。注意,看不见并不等于不存在!

  4. 所有的 UNIX 系统都支持:/dev/stdin/dev/stdout/dev/stderr 这三个特殊的文件名,它们也可以用 0、1、2 号文件描述符来描述。

  5. fmt.Println(), fmt.Print(), and fmt.Printf() 用于打印,fmt.Sprintln(), fmt.Sprint(), fmt.Sprintf() 用于生成字符串,fmt.Fprintln(), fmt.Fprint(), fmt.Fprintf() 用于写文件。

  6. 短赋值符 := 不能用于函数之外,因此全局变量只能用 var 声明。

  7. 下面的代码用于从标准输入读取数据,每读出一行就打印出来:

func main() {var f *os.Filef = os.Stdindefer f.Close()scanner := bufio.NewScanner(f)for scanner.Scan() {fmt.Println(">", scanner.Text())}
}

按 ctrl+D 退出循环,因为 ctrl+D 会告知程序没有更多的数据可以读取。

  1. os.Args 可以记录通过命令行输入的参数,并且它的类型是 []string,第一个元素是程序名,之后的为输入参数。例如:

go run a.go 10 1

os.Args[/tmp/go-build059507490/b001/exe/cla 10 1]

  1. 关于 docker 的命令:

# 根据 tag 创建
docker build -t go_hw:v1 .# 列出所有的 docker images
docker images# 运行
docker run go_hw:v1# 删除(-f 强制删除)
docker rmi 5a0d2473aa96 f56365ec0638
  1. 关于 Go 的垃圾回收算法:并发标记清除、非分代、非整理,使用写屏障。

  2. Go 为了降低 GC 的停顿时间,让 GC 和用户程序并发执行。为了让三色标记的结果不受并发执行的程序的影响,在整个标记过程中,要确保一个不变性:黑色集合里的对象保证不会指向白色集合里的对象,注意这并不影响一个白色对象指向黑色对象。我们把用户程序称为 mutator,mutator 运行了一个 writer barrier,每次当堆上有对象的指针(如果是对象的非指针字段变化,不影响)发生了变化,说明此对象可达,就要运行 writer barrier,将它变成灰色。mutator 通过 writer barrier 保证“黑色集合里的对象保证不会指向白色集合里的对象”这一不变性。这会带来性能的损耗,但这是并发执行用户程序和 GC 的代价。

  3. 垃圾回收器会在 channel 不可达时回收它,即使 channel 还未关闭。

  4. time go run xx.go 可以计算运行程序花费的时间。

  5. Please remember that at the end of the day, all programs that work on UNIX machines end up using C system calls to communicate with the UNIX kernel and perform most of their tasks. 所有在 UNIX 系统上运行的程序最终都会通过 C 系统调用来和内核打交道。用其他语言编写程序进行系统调用,方法不外乎两个:一是自己封装,二是依赖 glibc、或者其他的运行库。Go 语言选择了前者,把系统调用都封装到了 syscall 包。封装时也同样得通过汇编实现。

  6. strace ls 查看都有哪些系统调用,-c 可以计数。

  7. 将 .go 文件转化成汇编代码时,可指定操作系统和架构:

# 两者等价
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.

  1. go build -x defer.go 展示 build 过程。

  2. 数组可以用 “:” 变成切片:array4[0:] 或 array4[:],copy 函数只接收切片作为参数。

  3. 什么时候使用指针:1. 可以 share data,尤其是在函数之间;2. 区别某个变量是未设置还是真的零值。

  4. 关于 strings 有很多有意思的方法,例如 Repeat, Fields 等等,在这里[1]可以看到很多。

  5. Go container 包有 heap/list/ring 这几个组件。

  6. math/rand 可用于生成伪随机数;更安全的生成随机数:crypto/rand

  7. 关于可变参数的函数(A variadic function),...Type 称为 pack operator,而 Slice... 则被称为 unpack operator。一个可变参数的函数只能使用一次 pack operator。

  8. 安装一个本地包:

$ 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. 关于 Go 版本,例如 v1.2.3,v1/v2/v3 通常是不兼容的,1 表示大版本,2 表示 feature,3 表示 fix。

  2. 如何和 gomod 工作:

$ 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
  1. 创建 v2 版本:

git commit -a -m "using v2.0.0"
git tag v2.0.0
git push --tags origin v2
git --no-pager branch -a
  1. 使用 go mod vendor 命令来将依赖放到 vendor 文件夹里:

go mod init useV1V2
go mod vendor
  1. 查找哪些 go 源文件使用了 syscall:

grep \"syscall\" `find /usr/local/go/src -name "*.go"`
  1. 要记住的是在绝大部分程序里不需要使用反射,所以我们得弄清楚为什么反射是必须的以及什么时候需要使用反射。反射在实现 fmt, text/template, html/template 时是必须的。例如在 fmt 包里,反射可以让你不需要明确处理所有的类型,你当然可以明确处理你知道的所有类型,但你仍然不可能处理 All possible types。

  2. 什么时候用反射:Therefore, you might need to use reflection when you want to be as generic as possible or when you want to make sure that you will be able to deal with data types that do not exist at the time of writing your code but might exist in the future. Additionally, reflection is handy when working with values of types that do not implement a common interface.

  3. 反射不好的三点:a. 大量的反射会造成程序代码难以理解和维护。一个可行的解决方法是清晰的文档注释,但众所周知,程序员是最不愿意写文档的人;b. 相比正常的数据结构,反射是动态地“决定”数据结构,因此会更慢。这些动态代码也会使得一些代码工具更难执行重构和分析;c. 反射的错误在 build 期间不会被捕获,很多都是在运行期间直接 crash 整个程序。而且这经常是在程序正常运行数月甚至是数年之后才会爆发。一个可行的办法是大量的测试,但这也不太可能覆盖完全,并且会让代码库更加庞大。

  4. Go 不是一门面向对象的语言,但它可以模拟面向对象语言的某些功能。

  5. flag.var 可以解析用逗号分隔的多个值。

  6. wc 命令的结果有三列,分别表示行数、word 数,以及字节数。平时用的最多的是 wc -l,表示行数;wc -w 表示 wrod 数;wc -c 表示字节数。

  7. 如何输出一个文件的权限,上代码:

package mainimport ("fmt""os"
)func main() {arguments := os.Argsif 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])
}
  1. 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

  2. 最常用来发送信号的方式用 kill 命令,默认发送的是 SIGTERM 信号。kill -l 命令可以列出所有支持的信号。

  3. go run -race xx.go 可以显示有竞争冲突的代码。

  4. diff pipeline.go plNoRace.go --color 显示两个文件的 diff。

  5. Go 语言的并发模型是 fork-join 型的。使用 go 关键字启动子协程工作,使用 sync.Wait 和 channel 来收集结果。

  6. 可通过设置环境变量来改变 runtime.GOMAXPROCS(0) 的输出值:export GOMAXPROCS=800;

  7. sync.RWMutex 结构体里包含 sync.Mutex,即“读写锁”是在“锁”的基本上实现的。只有当所的读锁都 Unlock 了,写锁才能被 Lock。

  8. time go run xx.go 可以显示执行时间,包括 real, sys, user 的执行时间。

  9. 如果子 context 取消了,父 context 没有收到消息,那么在父 context 取消前就发生了内存泄露。

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.

  1. TAOCP——《计算机程序设计艺术》的作者高德纳(Donald Ervin Knuth)老爷子的一句经典的话:

"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!"

这告诉我们性能优化并不是主要工作,我们不要花费大量精力在这上面。

  1. 做优化的前提是程序没有 bug,所以如果你在程序的第一版就来优化是有问题的,因为 v1 版本可能经常有 bug。

  2. 交叉编译命令:env GOOS=linux GOARCH=386 go build xCompile.go。指定操作系统、指令集。

  3. 通过 bytes 包[2]的例子,可以看懂 godoc 和源码[3]里的 comments 的对应关系。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


资料分享,关注公众号回复指令:

  • 回复【加群】,和大佬们一起成长。

  • 回复【000】,下载一线大厂简历模板。

  • 回复【001】,送你 Go 开源电子书。

深度阅读之《Mastering Go》相关推荐

  1. 【论文阅读】Mastering the game of Go with deep neural networks and tree search

    [论文阅读]Mastering the game of Go with deep neural networks and tree search 1 本文解决了什么问题? 在所有的 完全信息博弈 中, ...

  2. 深度阅读之《Concurrency in Go》

    很多朋友可能都知道,年前我从滴滴跑路,来了字节跳动,并且很快就写了篇传播甚广的弱智找 bug 文章:<"���"引发的线上事故>,之后就再也没动静了-- 当然最主要的原 ...

  3. 深度阅读:阿杜威少快意江湖 昆汀式的刀光剑影

    2014年5月的俄克拉荷马正迎来一片喧嚣,凯文-杜兰特在熠熠发光的常规赛MVP奖杯旁边说到:"我爱他,你都是知道的,当然有些时候我们之间也都彼此不喜欢,但这很正常吧,我敢保证只要是有兄弟和好 ...

  4. 深度阅读:详细剖析 extern “C“

    [导读]:本文详细解析extern "C"的底层原理与实际应用. 以下是正文 在你工作过的系统里,不知能否看到类似下面的代码. 这好像没有什么问题,你应该还会想:"嗯⋯是 ...

  5. 【深度好文】沈向洋:读论文的三个层次

    5月14日,沈向洋博士在全球创新学院(GIX)课程上曾做了一场线上公开课<You are how you read>,分享他对于科研论文阅读.撰写的宝贵经验,引起一时轰动.由于围观网友太多 ...

  6. 阅读APP,为什么都开始抢kindle生意了?

    作者/易牟 来源/螳螂财经(ID:TanglangFin) 你有多久没看完一本书了? 在知识焦虑肆虐的年代,一个好的阅读工具,也不再是文艺青年的专属,对于大多数人而言,数字阅读更成了一种主流. 前有k ...

  7. 安卓系统dicom阅读器_用户分享:电子书阅读器Note Pro,一座贴心的移动图书馆...

    本文转载自"什么值得买"官网用户"小良读书",经作者授权转载. Note Pro,一座贴心的移动图书馆 移动图书馆 貌美的小书郎 10.3寸高清大屏更适合专业书 ...

  8. 机器阅读理解首次超越人类!云从刷新自然语言处理新纪录

    媒体动态发展历程资质荣誉人才招聘 机器阅读理解首次超越人类!云从刷新自然语言处理新纪录 2019-03-11 10:06 浏览:454 近日,云从科技和上海交通大学在自然语言处理领域取得重大突破,在卡 ...

  9. 从阅读空间到QQ阅读,一个web2.0向web1.0的倒退的产品

    最近,QQ邮箱的阅读空间要取消了,转向QQ阅读. 作为一个长期的阅读空间用户,不禁因为这样的趋向而感到这个产品的前途堪忧. 记得一年之前,分析阅读空间中的分享功能,能够将一向单调,让人感觉孤独的阅读器 ...

最新文章

  1. php imap 安装_linux 下安装PHP的IMAP扩展实现邮件收发
  2. 初探JavaScript(一)——也谈元素节点、属性节点、文本节点
  3. python 画图_学python画图最快的方式——turtle小海龟画图
  4. 软件架构设计最佳实践
  5. ActiveMQ安装配置
  6. MySQL单列索引和组合索引的创建及区别介绍
  7. hb:一个简单的 http/web bench 工具
  8. Lightroom Classic 教程,如何在 Lightroom 中创建黑色电影效果?
  9. [C# 开发技巧]实现属于自己的截图工具
  10. oracle实现累加,oracle用sum函数实现累加
  11. 解决 Win11 资源管理器卡顿
  12. 12.5m分辨率DEM数据?解读ASF DAAC的DEM数据--关于地理数据收集与处理的基本工具推荐(5)
  13. Flink On K8S终极实现方案
  14. Android项目实践(二)——日记本APP
  15. “隐藏高手” 胰腺癌的新出路——微生物
  16. Excel中SEARCH函数的使用方法
  17. 【手把手教程】如何快速实现任意自定义的域名的网页跳转
  18. java实现手写签名_手写签字,保存笔迹到图片
  19. excel教程中daverage函数应用实例(一):统计部门平均工资
  20. 经典力学中最难的问题,至今没有答案

热门文章

  1. python爬取12306_python爬取12306的车次信息
  2. performance 查看页面性能
  3. Fastreport.Net用户手册:报表页
  4. Node.js与Sails~Model数据模型
  5. 实现ISA Server 2006物理机到VMware ESX 4虚拟机的迁移
  6. Gearman 异步处理委派任务
  7. loopback的作用
  8. 2021HDU多校8 - 7057 Buying Snacks(矩阵快速幂套NTT优化dp)
  9. CodeForces - 731D 80-th Level Archeology(线段树+暴力/差分)
  10. CodeForces - 681D Gifts by the List(思维)