Changkun's Blog欧长坤的博客

Science and art, life in between.科学与艺术,生活在其间。

  • Home首页
  • Ideas想法
  • Posts文章
  • Tags标签
  • Bio关于
Changkun Ou

Changkun Ou

Human-AI interaction researcher, engineer, and writer.人机交互研究者、工程师、写作者。

Bridging HCI, AI, and systems programming. Building intelligent human-in-the-loop optimization systems. Informed by psychology, philosophy, and social science.连接人机交互、AI 与系统编程。构建智能的人在环优化系统。融合心理学、哲学与社会科学。

Science and art, life in between.科学与艺术,生活在其间。

276 Blogs博客
165 Tags标签
Changkun's Blog欧长坤的博客

Go 1.16 Big ChangesGo 1.16 的重大变化

Published at发布于:: 2021-01-27

Go 1.16 has released many very interesting changes. Here is a brief summary:

russ cos: deprecated.

  • https://twitter.com/_rsc/status/1351676094664110082
  • https://go-review.googlesource.com/c/go/+/285378
  • https://github.com/golang/go/issues/43724
  1. Support for darwin/arm64
    1. Issues encountered supporting darwin/arm64
      • Apple’s bug: related to signal preemption
    2. Apple Silicon M1 performance
      • But crypto performance is poor
      • Release cycle: https://github.com/golang/go/wiki/Go-Release-Cycle
    3. Compiler bootstrapping process
  • Installing Go: https://gist.github.com/Dids/dbe6356377e2a0b0dc8eacb0101dc3a7

  • https://github.com/golang/go/issues/42684

    • Kernel Panic Episode 62: Your Computer Isn’t Yours, Code Signing, OCSP Server
    • Ken Thompson Turing Award lecture: Reflections on Trusting Trust
      • TODO
    • Apple’s long-standing code signing issues; I encountered similar problems doing Electron in the early days, and these issues still exist today
  • Asynchronous preemption random crashes, a Rosetta bug: https://github.com/golang/go/issues/42700

  • Bootstrapping, installation confusion: https://github.com/golang/go/issues/38485#issuecomment-735360572

    • Go’s bootstrapping consists of three steps
        1. 1.4 C version TODO
        1. tool chain 1
        1. tool chain 2
        1. tool chain 3
  • Run x86 programs under Rosetta: arch --x86_64

  • M1 compatibility status in dotfiles: https://github.com/changkun/dotfiles/issues/2

    • https://doesitarm.com/
    • https://isapplesiliconready.com/
  • Got it in early December, have been using it for almost two months now — very smooth, battery life is incredible

  • My essential third-party software list:

    • homebrew (compatibility is not great, but fortunately most dependent software is written in Go, and Go’s support is very complete)
      • Breaks compatibility casually, removes software distribution — there was a tool called rmtrash that I had been using since around 2014, but it was removed from distribution last year, so I wrote a fully compatible tool changkun.de/s/rmtrash, but it wasn’t merged; they said it needed to be approved by the original author to bypass popularity restrictions, but the original author is unreachable
    • vscode (have been using Insider long-term)
    • macvim
    • tmux
    • oh-my-zsh
    • Blender (Cycles ray tracing doesn’t support GPU, but editing meshes with less than a million vertices is fine)
    • iTerm: supports M1
    • Chrome: supports M1
    • MacTex: supports M1
    • Docker: released support a week before Christmas, works perfectly, no issues so far
  1. Go Modules changes

    1. Collecting feedback
    2. Complex dependency management — what’s the most complex project dependency you’ve managed in practice, how many modules, and what do you write for each dependency upgrade? What did you use before Go modules?
      1. My experience: Go vendor, 1.10 dep, 1.11 go modules
      2. GOPATH project management — although GOPATH has been removed, I still follow the GOPATH convention
    3. Minimum version selection
      1. Semantic Versioning: major.minor.patch
      2. The classic diamond dependency problem: A depends on B and C, B and C each depend on different versions of D that are incompatible, so no specific version of D can be selected — semantic import versioning eliminates this by adding the major version number requirement at the end of the import path /v2
      3. dep doesn’t allow diamond dependencies, upgrades are very difficult
      4. Build reproducibility — without a lock file, >= dependencies change over time
      5. Select the minimum usable version — builds don’t change over time
      6. https://www.youtube.com/watch?v=F8nrpe0XWRg&ab_channel=SingaporeGophers
      7. Misunderstood working methods
      8. GOPATH
      9. vendor
      10. Three key points
      11. Compatibility
      12. Reproducibility
      13. Cooperation (often overlooked by many)
    4. Go Modules enabled by default, go build must include go.mod file, otherwise compilation fails
    5. build/test will not upgrade modules
    6. Default -mod=vendor
  2. File system interface

    1. Why is the fs.FS abstraction important

      1. Unix file system abstract always disk blocks
      2. Network file systems (Upspin) abstract away machines
      3. REST abstracts nearly anything
      4. cp doesn’t care whether it’s moving file blocks, or even where the file is — it could be different disks or different machines
      5. Defines the “generics” for any file type tools
    2. What major changes it caused

      1. io/ioutil
        1. Russ Cox’s explanation of deprecated in Go (https://twitter.com/_rsc/status/1351676094664110082)
        2. https://www.srcbeat.com/2021/01/golang-ioutil-deprecated/
      2. Other fs abstractions
      3. Rob Pike’s 2016/2017 Gopherfest, Upspin, Changkun’s Midgard
        1. https://www.youtube.com/watch?v=ENLWEfi0Tkg&ab_channel=TheGoProgrammingLanguage
        2. FUSE: filesystem in userspace
        3. https://changkun.de/s/midgard
        4. Every user has a private root, no global root, r@golang.org/some/stuff, user names look like email addresses
        5. Access control defined by plain text files read: r@golang.org, ann@example.com
      4. Currently a very simple implementation, just a read-only file system
      5. ReadDir and DirEntry
        1. https://benhoyt.com/writings/go-readdir/
      6. Extensible directions: memoryFS, support for writing back to disk, hashFS for CDN support
      7. Remaining issues… e.g. 44166
      1
      2
      3
      4
      5
      6
      7
      
      import _ "embed"
      //go:embed a.txt
      var s string
      
      import "embed"
      type embed.String string
      var s embed.String
      
      1
      
      
      
  3. File embedding //go:embed

    1. Basic functionality of the new feature
    2. Some possible applications
    3. Some features discussed during the feature freeze cycle
    4. https://blog.carlmjohnson.net/post/2021/how-to-use-go-embed/
  4. Runtime memory management

    1. Return to MADV_DONTNEED
    • https://blog.changkun.de/posts/pss-uss-rss/
    1. New monitoring infrastructure runtime/metrics
    • Previous monitoring functions: runtime.ReadMemStats, debug.GCStats
    • runtime/metrics:
      • metrics.All()
      • Issue 37112
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package main

import (
	"fmt"
	"runtime/metrics"
)

func main() {
	// Get descriptions for all supported metrics.
	descs := metrics.All()

	// Create a sample for each metric.
	samples := make([]metrics.Sample, len(descs))
	for i := range samples {
		samples[i].Name = descs[i].Name
	}

	// Sample the metrics. Re-use the samples slice if you can!
	metrics.Read(samples)

	// Iterate over all results.
	for _, sample := range samples {
		// Pull out the name and value.
		name, value := sample.Name, sample.Value

		// Handle each sample.
		switch value.Kind() {
		case metrics.KindUint64:
			fmt.Printf("%s: %d\n", name, value.Uint64())
		case metrics.KindFloat64:
			fmt.Printf("%s: %f\n", name, value.Float64())
		case metrics.KindFloat64Histogram:
			// The histogram may be quite large, so let's just pull out
			// a crude estimate for the median for the sake of this example.
			fmt.Printf("%s: %f\n", name, medianBucket(value.Float64Histogram()))
		case metrics.KindBad:
			// This should never happen because all metrics are supported
			// by construction.
			panic("bug in runtime/metrics package!")
		default:
			// This may happen as new metrics get added.
			//
			// The safest thing to do here is to simply log it somewhere
			// as something to look into, but ignore it for now.
			// In the worst case, you might temporarily miss out on a new metric.
			fmt.Printf("%s: unexpected metric Kind: %v\n", name, value.Kind())
		}
	}
}

func medianBucket(h *metrics.Float64Histogram) float64 {
	total := uint64(0)
	for _, count := range h.Counts {
		total += count
	}
	thresh := total / 2
	total = 0
	for i, count := range h.Counts {
		total += count
		if total > thresh {
			return h.Buckets[i]
		}
	}
	panic("should not happen")
}
  1. Other noteworthy features
    1. os/signal.NotifyContext
    2. Memory model fixes
    3. Linker optimizations

Go 1.16 发布了非常多非常有趣的变,尝试做一个简单的总结:

russ cos: deprecated.

  • https://twitter.com/_rsc/status/1351676094664110082
  • https://go-review.googlesource.com/c/go/+/285378
  • https://github.com/golang/go/issues/43724
  1. 支持 darwin/arm64
    1. 支持 darwin/arm64 上遇到的问题
      • 苹果的bug: 与信号抢占有关
    2. Apple Silicon M1 性能
      • 但是在加密上性能很差
      • 发版周期:https://github.com/golang/go/wiki/Go-Release-Cycle
    3. 编译器自举过程
  • 安装 Go:https://gist.github.com/Dids/dbe6356377e2a0b0dc8eacb0101dc3a7

  • https://github.com/golang/go/issues/42684

    • 内核恐慌的第 62 期:你的电脑不是你的,代码签名,OCSP Server
    • ken thompson 图灵奖演讲:reflections on trusting trust
      • TODO
    • 苹果代码签名的老问题,早年做 electron 也是这类问题,现在这样的问题还是存在
  • 异步抢占随机崩溃,是 Rosetta 的 Bug:https://github.com/golang/go/issues/42700

  • 自居,安装的困惑:https://github.com/golang/go/issues/38485#issuecomment-735360572

    • Go 语言的自举分为三个步骤
        1. 1.4 C version TODO
        1. tool chain 1
        1. tool chain 2
        1. tool chain 3
  • 在 Rosetta 下运行 x86 程序:arch --x86_64

  • dotfiles 中关于 M1 的兼容性情况:https://github.com/changkun/dotfiles/issues/2

    • https://doesitarm.com/
    • https://isapplesiliconready.com/
  • 十二月初入手 如今已经使用快两个月了 非常流畅 续航逆天

  • 我的必备第三方软件列表:

    • homebrew (支持性不好,好在现在大部分依赖的软件是用 Go 写的,而且 Go 的支持非常完善)
      • 不考虑兼容性 随意破坏兼容性移除软件分发,有一个 rmtrash 的工具,我从2014年左右就开始使用,但是去年被从软件分发中移除了,所以自己写了一个全兼容的工具changkun.de/s/rmtrash,但没有被合并,他们说了要被原软件作者任何才能不受受欢迎程度的限制,但实际上软件作者已经联系不到了
    • vscode(已在长期使用 Insider)
    • macvim
    • tmux
    • oh-my-zsh
    • Blender(Cycles 光追渲染不支持 GPU,但编辑顶点小于百万级别的网格是没有问题的)
    • iTerm:支持 M1
    • Chrome:支持 M1
    • MacTex:支持 M1
    • Docker:圣诞节前一周发布支持,很完美,至今没有遇到问题
  1. Go Modules 的变更

    1. 收集反馈
    2. 复杂依赖管理,你实践中管理过最复杂的项目依赖多少模块,每次依赖升级都有写什么?在没有 Go modules 之前你用的是什么?
      1. 我的经历:Go vendor, 1.10 dep, 1.11 go modules,
      2. GOPATH 的项目管理,现在虽然移除了 gopath,但我还是沿用了 gopath 的习惯
    3. 最小版本选择
      1. Semantic Versioning: major.minor.patch
      2. 经典的钻石依赖问题:A依赖B和C,BC分别依赖 D 的不同版本,而这两个版本的 D 不兼容,所以无法在依赖中选取一个特定的D版本,semantic import versioning 消除了这种依赖,在import path的最后添加了主版本号的要求/v2
      3. dep 不允许钻石依赖,升级非常难
      4. 构建的可重复性,没有lock文件,>=的依赖会随着时间的变化而变化
      5. 选择最小的可以依赖的版本,构建不会随时间的变化而变化
      6. https://www.youtube.com/watch?v=F8nrpe0XWRg&ab_channel=SingaporeGophers
      7. 不被理解的工作方式
      8. GOPATH
      9. vendor
      10. 三大要点
      11. 兼容性
      12. 可重复性
      13. 合作(通常被很多人忽略)
    4. 默认启用 Go Moduels, go build 必须包含 go.mod 文件,否则编译失败
    5. build/test 不会升级 modules
    6. 默认 -mod=vendor
  2. 文件系统接口

    1. fs.FS 抽象的重要性在哪里

      1. unix file system abstract always disk blocks
      2. network file systems (upspin) abstract away machines
      3. rest abstract nearly anything
      4. cp 不关心是否移动文件的区块,甚至不关心文件在哪个位置,可能是不同的磁盘也可能是不同的机器
      5. 定义任何文件类型工具的「泛型」
    2. 导致了哪些主要变化

      1. io/ioutil
        1. Russ cox 对 deprecated 在 go 中的解释(https://twitter.com/_rsc/status/1351676094664110082)
        2. https://www.srcbeat.com/2021/01/golang-ioutil-deprecated/
      2. 其他 fs 的抽象
      3. Rob Pike 的 2016/2017 Gopherfest, Upspin、Changkun 的 Midgard
        1. https://www.youtube.com/watch?v=ENLWEfi0Tkg&ab_channel=TheGoProgrammingLanguage
        2. FUSE: filesystem in userspace
        3. https://changkun.de/s/midgard
        4. every user has a private root, no global root, r@golang.org/some/stuff, user names look like email address
        5. access control defined by plain text files read: r@golang.org, ann@example.com
      4. 目前的非常简单的实现,只是一个只读文件系统
      5. ReadDir and DirEntry
        1. https://benhoyt.com/writings/go-readdir/
      6. 可扩展的方向:memoryFS,支持回写到磁盘、hashFS 为 CDN 提供支持
      7. 还存在的问题。。例如 44166
      1
      2
      3
      4
      5
      6
      7
      
      import _ "embed"
      //go:embed a.txt
      var s string
      
      import "embed"
      type embed.String string
      var s embed.String
      
      1
      
      
      
  3. 文件嵌入 //go:embed

    1. 新特性的基本功能
    2. 一些可能的应用
    3. 一些在feature freeze cycle 中才讨论出来的feature
    4. https://blog.carlmjohnson.net/post/2021/how-to-use-go-embed/
  4. 运行时内存管理

    1. 回归 MADV_DONTNEED
    • https://blog.changkun.de/posts/pss-uss-rss/
    1. 新的监控基础设施 runtime/metrics
    • 以前的监控函数:runtime.ReadMemStats, debug.GCStats,
    • runtime/metrics:
      • metrics.All()
      • Issue 37112
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package main

import (
	"fmt"
	"runtime/metrics"
)

func main() {
	// Get descriptions for all supported metrics.
	descs := metrics.All()

	// Create a sample for each metric.
	samples := make([]metrics.Sample, len(descs))
	for i := range samples {
		samples[i].Name = descs[i].Name
	}

	// Sample the metrics. Re-use the samples slice if you can!
	metrics.Read(samples)

	// Iterate over all results.
	for _, sample := range samples {
		// Pull out the name and value.
		name, value := sample.Name, sample.Value

		// Handle each sample.
		switch value.Kind() {
		case metrics.KindUint64:
			fmt.Printf("%s: %d\n", name, value.Uint64())
		case metrics.KindFloat64:
			fmt.Printf("%s: %f\n", name, value.Float64())
		case metrics.KindFloat64Histogram:
			// The histogram may be quite large, so let's just pull out
			// a crude estimate for the median for the sake of this example.
			fmt.Printf("%s: %f\n", name, medianBucket(value.Float64Histogram()))
		case metrics.KindBad:
			// This should never happen because all metrics are supported
			// by construction.
			panic("bug in runtime/metrics package!")
		default:
			// This may happen as new metrics get added.
			//
			// The safest thing to do here is to simply log it somewhere
			// as something to look into, but ignore it for now.
			// In the worst case, you might temporarily miss out on a new metric.
			fmt.Printf("%s: unexpected metric Kind: %v\n", name, value.Kind())
		}
	}
}

func medianBucket(h *metrics.Float64Histogram) float64 {
	total := uint64(0)
	for _, count := range h.Counts {
		total += count
	}
	thresh := total / 2
	total = 0
	for i, count := range h.Counts {
		total += count
		if total > thresh {
			return h.Buckets[i]
		}
	}
	panic("should not happen")
}
  1. 其他值得一提的特性
    1. os/signal.NotifyContext
    2. 内存模型修复
    3. 链接器优化
© 2008 - 2026 Changkun Ou. All rights reserved.保留所有权利。 | PV/UV: /
0%