Go 语言官方 10 年博文: 深度阅读指引与重点内容摘录

Tags: golang 

本篇目录

说明

一个多月前,Go 的网站发了一篇博文《Go Turns 10》,心里一惊,它已经诞生 10 年了!

10 年里,Go 发布的几十篇博文介绍了 Go 的方方面面,是获得 Go 语言最新进展和能力的不二之选。

Go 2 进展

Toward Go 2:Go 2 启动,5 年实际应用后,Go 语言从推广转向进化

Go 2, here we come!:Go 2 的进展

Next steps toward Go 2:Go 2 的进展

Why Generics?:正在进行中的范型设计

代码管理

Godoc: documenting Go code:注释文档

Organizing Go code:package 组织方式的官方建议

Go Modules in 2019:go modules 全面替换 GOPATH

Using Go Modules:go module 的使用方法

Migrating to Go Modules:怎样迁移到 go module

Publishing Go Modules:go module 发布与版本规范

Go Modules: v2 and Beyond:主版本发生变换时的操作

Module Mirror and Checksum Database Launched:go module 背后的机制

  • 切换为 go module 后,import 使用的是 go module 的别名(不再是路径)
  • 如果引用主版本,必须使用版本后缀,例如 /v2
  • 测试代码等不能使用依赖 GOPATH 的文件

A Proposal for Package Versioning in Go:详细介绍了 go module 的设计过程

测试用例

The cover story:go 的测试覆盖率工具 -cover

  • go test -cover

Testable Examples in Go:怎样写和文档融合在一起的示例

Using Subtests and Sub-benchmarks:测试用例和基准测试的增强功能

调试调优

Debugging Go code (a status report):go 语言程序的最开始调试方法

Debugging what you deploy in Go 1.12:go 1.12 进一步优化了调试工具,使用 delve

Go 开发的程序,最开始的调试方法只有日志和 gdb,并且是支持 DWARF 的 gdb 7+,并且不支持 channel、interface 等等。现在好很多了,可以用 delve,另外对 gdb 继续支持(不好用):

Profiling Go Programs:非常重要,go 的性能诊断工具 pprof

  • 堆栈采样,发现占用 CPU 最多的函数;
  • 360 曾经分享他们的 经验,做了一个在线运行的 go 程序的状态采集和展示,挺有意义;
  • Qihoo 360 and Go 中对垃圾回收的规避经验特别重要,简单说就是避免短时协程;

Smaller Go 1.7 binaries:可执行文件体积压缩了 30% 以上

  • We could take more radical steps to reduce binary size: the upx tool for compressing executables shrinks binaries by another 50% at the cost of increased startup time and potentially increased memory use.

错误处理

Defer, Panic, and Recover :defer 的规则,以及 panic 和 recover

defer 规则:

  1. A deferred function’s arguments are evaluated when the defer statement is evaluated.(入参值是 defer 时的值)
  2. Deferred function calls are executed in Last In First Out order after the surrounding function returns.(后进先出)
  3. Deferred functions may read and assign to the returning function’s named return values.(可以修改命名返回值,这个特性还是不用为好)

panic 规则:

  1. 被调用时,终止所在函数 defer 以外指令的继续执行;
  2. 所在函数的 defer 都执行完成后,返回上一级调用者;
  3. 对上级调用来说,被 panic 的函数等同于 panic,按上面两条规则处理;
  4. 逐级向上返回,直到所在的 gorouine 退出。

recover 规则:

  1. recover 在 defer 中使用,终止 panic 的向上传递,当前函数正常退出。

Error handling and Go:go 的 error 处理

Working with Errors in Go 1.13: go 1.13 引入的 error 语法糖

内存管理

Go GC: Prioritizing low latency and simplicity:go1.5 引入的新的 gc 方法

  • If you want to lower the total time spent in GC, increase GOGC. If you want to trade more GC time for less memory, lower GOGC.

Getting to Go: The Journey of Go’s Garbage Collector: go 垃圾回收机制的演变

常规细节

Go Slices: usage and internals:go 的 slice 不是数组。

  • slice 不是数组, slice 不是数组,slice 不是数组,重要的事情说三遍。
  • Go 语言中数组是有长度的,并且长度写到类型属性中,[3] int[4] int 是不同的类型
  • Go 的数组变量是「值」,不是指向数组的指针(不同于 C 语言)
  • Go 的数组变量是「值」,所以传递的时候,都是 copy 了一份!
  • Slice 是一种依赖于数组的类型,它包含指定数组内成员指针
  • Slice 的 cap 是底层数组的长度,slice 的 index 运算超出 cap 时会 panic
  • copy() 和 append () 是分别用来进行 slice 复制和追加的内置函数
  • Slice 的使用极其富有技巧性,使用不当会严重降低运行效率和浪费内存,上文要认真读

JSON and Go:json 序列化和反序列化,Reference Types 的处理值得关注

  • 反序列化使用的字符串中没有 Reference Types 的对应值,那么 Reference Types 为 nil
  • 如果有,反序列化时会分配相应的内存空间
  • 上面两点意味着在 struct 中使用 Reference Types 可以减少开销

Go maps in action:map(哈希表)的方方面面,非并发安全

Arrays, slices (and strings): The mechanics of append:append 的实现方法,复制时机

  • 数组最常用的功能是作为 slice 的底层数组
  • slice 的 index 操作是“左开右闭”
  • slice 作为参数按值传递时,复制的值是 slice header,底层数组不复制
  • 搞清楚要修改的是 slice header 还是 slice 指向的数组
  • 使用 make 创建 slice 时,cap 默认等于 len
  • append 的时候,如果超出了 cap,会引发扩容、复制
  • string 是只读的 slice,底层是 byte 数组
// Insert inserts the value into the slice at the specified index,
// which must be in range.
// The slice must have room for the new element.
func Insert(slice []int, index, value int) []int {
    // Grow the slice by one element.
    slice = slice[0 : len(slice)+1]
    // Use copy to move the upper part of the slice out of the way and open a hole.
    copy(slice[index+1:], slice[index:])
    // Store the new value.
    slice[index] = value
    // Return the result.
    return slice
}

Constants:constant 与变量的区别,const 不需要类型转换

  • 有类型常量和无类型常量是完全不同的
  • 这一篇相当烧脑,特别是 constant 的默认类型

并发编程

Share Memory By Communicating: Go 语言设计思想,通过传递指针的方式使用共享内存

多线程编程时,经常通过共享内存实现线程间的通信,需要非常小心的处理加锁和解锁的时机。 Go 语言提供了互斥锁、读写锁,但是更鼓励用 channel 传递指针的方式实现。用 channel 保证同一时刻,只有一个协程在处理目标变量。

Go Concurrency Patterns: Timing out, moving on:一种设置等待超时的方法

在 select 中放一个定时 channel:

select {
case <-ch:
    // a read from ch has occurred
case <-timeout:
    // the read from ch has timed out
}

Concurrency is not parallelism:并发不等于并行,一段 30 分钟的视频

Advanced Go Concurrency Patterns:更深入了介绍了并发的问题,又一段 30 分钟视频

这两段视频,抽时间看一下。。。

Introducing the Go Race Detector:竞争检测工具 -race

  • 怎样通过一个 channel 同时关闭所有 goroutine?(用 close 关闭 channel)

Go Concurrency Patterns: Context:用 context 串联相关的 goroutine

  • At Google, we require that Go programmers pass a Context parameter as the first argument to every function on the call path between incoming and outgoing requests.

Go Concurrency Patterns: Pipelines and cancellation:go channel 的经典用法

多语言处理

Strings, bytes, runes and characters in Go:byte、character 和 rune 的区别

  • unicode/utf8 处理 utf8 字符的库

下面这段代码的 index 的值,很有意思:

const nihongo = "日本語"
for index, runeValue := range nihongo {
    fmt.Printf("%#U starts at byte position %d\n", runeValue, index)
}

Text normalization in Go: 处理 utf8 字符时应该注意的问题

  • 关键:一个字符可能由多个 rune 组成
  • utf8 编码有两种方式,看的头大…

Language and Locale Matching in Go:用户语言与应用支持的语言的搭配策略

扩展能力

C? Go? Cgo!:在 Go 代码中引用 C 代码的方法

Gobs of data:Go 新开发的编码和使用方式

Gobs 的优势没看懂,编码方面的知识需要恶补

Spotlight on external Go libraries:几个比较实用的外部库

The Laws of Reflection:反射的设计和用法

Go 提供了几个图片处理的库,挺有意思,找时间学习:

Generating code:代码自动生成 go:generate

Introducing HTTP Tracing:跟踪 http 请求调用过程的方法

HTTP/2 Server Push:http/2 的主要特点、使用方法和注意事项

Portable Cloud Programming with Go Cloud:go 的跨云运行方案

What’s new in the Go Cloud Development Kit

Compile-time Dependency Injection With Go Cloud’s Wire:依赖注入工具 wire

使用经验

Real Go Projects: SmartTwitter and web.go:Smart Twitter

Go at Heroku:使用 Go 实现 Paxos 协议的经历

From zero to Go: launching on the Google homepage in 24 hours:用 go 实现 google 主页

Building StatHat with Go:使用 go 开发的 stathat

  • stathat 是一个收集时间序列的在线服务,有 1.6 万个用户!商业上的启发更大!

Inside the Go Playground:go Playground 的实现

社区资源

Introducing the Go Playground:go 在线运行

Go for App Engine is now generally available:gae 支持 go runtime

Go and the Google Cloud Platform

Go on App Engine: tools, tests, and concurrency

Announcing App Engine’s New Go 1.11 Runtime

The New Go Developer Network:分布在全球各地的 go 小组

Go.dev: a new hub for Go developers:Go 代码仓库

Hello, 中国!:中国镜像站 https://golang.google.cn

Release 记录

20120328 Go version 1 is released

20131201 Go 1.2 is released

  • scheduler 会被不定时唤起,解决了单线程时,go routine 霸占线程的问题。

20140618 Go 1.3 is released

20141110 Go 1.4 is released

  • 支持 android,可以用 go 开发 android app, golang.org/x/mobile
  • go generate

20150819 Go 1.5 is released

  • 编译器完全用 go 实现,完成自举
  • 垃圾回收机制重新设计,gc pause 时间大幅缩短

20160217 Go 1.6 is released

  • 支持 http2
  • gc pause 时间进一步缩短

20160815 Go 1.7 is released

  • 引入 context
  • gc pause 时间进一步缩短

20170216 Go 1.8 is released

  • gc pause 时间缩短到10毫秒级

20170824 Go 1.9 is released

  • 支持 type aliases
  • sync 提供了并发安全的 map

20180216 Go 1.10 is released

20180824 Go 1.11 is released

  • 支持 go module
  • 支持 WebAssembly(在浏览器中运行)

20190225 Go 1.12 is released

20190903 Go 1.13 is released

  • go module 成为默认设置

参考

  1. 李佶澳的博客

推荐阅读

Copyright @2011-2019 All rights reserved. 转载请添加原文连接,合作请加微信lijiaocn或者发送邮件: [email protected],备注网站合作

友情链接:  系统软件  程序语言  运营经验  水库文集  网络课程  微信网文  发现知识星球