-
Notifications
You must be signed in to change notification settings - Fork 0
/
README.html
231 lines (231 loc) · 17.4 KB
/
README.html
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>Go-1.16-and-beyond</title>
<style>
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
span.underline{text-decoration: underline;}
div.column{display: inline-block; vertical-align: top; width: 50%;}
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
ul.task-list{list-style: none;}
pre > code.sourceCode { white-space: pre; position: relative; }
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
pre > code.sourceCode > span:empty { height: 1.2em; }
.sourceCode { overflow: visible; }
code.sourceCode > span { color: inherit; text-decoration: inherit; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
pre > code.sourceCode { white-space: pre-wrap; }
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
}
pre.numberSource code
{ counter-reset: source-line 0; }
pre.numberSource code > span
{ position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span > a:first-child::before
{ content: counter(source-line);
position: relative; left: -1em; text-align: right; vertical-align: baseline;
border: none; display: inline-block;
-webkit-touch-callout: none; -webkit-user-select: none;
-khtml-user-select: none; -moz-user-select: none;
-ms-user-select: none; user-select: none;
padding: 0 4px; width: 4em;
color: #aaaaaa;
}
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
div.sourceCode
{ }
@media screen {
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
</style>
<link rel="stylesheet" href="https://rawcdn.githack.com/edwardtufte/tufte-css/e225f3a0e5f8f42a1d28416c1c85962411711907/tufte.min.css" />
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->
</head>
<body>
<header id="title-block-header">
<h1 class="title">Go-1.16-and-beyond</h1>
</header>
<h1 id="a-quick-tour-of-go-116--16th-golang-leipzig-meetup">A quick tour of Go 1.16 @ 16th Golang Leipzig Meetup</h1>
<p>Our 16th Meetup at the 16th of February with a quick tour on Go 1.16 <span class="emoji" data-emoji="blush">😊</span> . We will also have an outlook on the Go generics proposal.</p>
<p><video controls loop autoplay><source src="golang-leipzig-stickers.mp4" type="video/mp4"></video></p>
<p>Go 1.16 is expected to be released this Februrary! <span class="emoji" data-emoji="tada">🎉</span> <span class="emoji" data-emoji="fireworks">🎆</span></p>
<h2 id="from-the-preliminary-release-notes">From the <a href="https://tip.golang.org/doc/go1.16#ioutil">preliminary release notes</a></h2>
<ul>
<li><span class="emoji" data-emoji="warning">⚠️</span> <a href="https://tip.golang.org/doc/go1.16#ioutil"><code>io/ioutil</code> gets deprecated</a>
<ul>
<li>package remains and will continue to work like before but new code should use functions from <code>io</code> and <code>os</code> instead</li>
<li><code>ioutil</code> functions will become wrappers around <code>io</code> and <code>os</code>, example <a href="https://tip.golang.org/src/io/ioutil/ioutil.go?s=1167:1213#L26"><code>ioutil.ReadFile</code></a></li>
</ul></li>
<li><span class="emoji" data-emoji="warning">⚠️</span> 32-bit iOS and macOS support is dropped</li>
<li><span class="emoji" data-emoji="tada">🎉</span> Go adds support for the 64-bit macOS ARM architecture (aka Apple Silicon) with <code>GOOS=darwin, GOARCH=arm64</code>
<ul>
<li><del>crypto will be slower on this architecture since the optimized assembly code is still missing</del> There are arm64 assembly implementations: <a href="https://tip.golang.org/src/crypto/aes/cipher_asm.go">https://tip.golang.org/src/crypto/aes/cipher_asm.go</a> and <a href="https://tip.golang.org/src/crypto/aes/asm_arm64.s">https://tip.golang.org/src/crypto/aes/asm_arm64.s</a></li>
</ul></li>
</ul>
<h4 id="modules"><a href="https://tip.golang.org/doc/go1.16#modules">Modules</a></h4>
<ul>
<li><span class="emoji" data-emoji="warning">⚠️</span> <code>GO111MODULE=on</code> is now the default, i.e. go tools work in <em>go modules</em> mode by default</li>
<li><code>go build</code> and <code>go test</code> do not modify your <code>go.mod, go.sum</code> anymore
<ul>
<li>those two commands report if an module or checksum needs to be added or updated</li>
<li>use <code>go get</code> or <code>go mod tidy</code> to do tha</li>
</ul></li>
</ul>
<h4 id="other">Other</h4>
<ul>
<li><span class="emoji" data-emoji="tada">🎉</span> <a href="https://tip.golang.org/pkg/runtime/metrics/"><code>runtime/metrics</code></a> is a new package that provides a stable interface for accessing runtime metrics
<ul>
<li>generalizes <a href="https://tip.golang.org/pkg/runtime/#ReadMemStats"><code>runtime.ReadMemStats</code></a> and others</li>
</ul></li>
<li><a href="https://tip.golang.org/pkg/runtime/#hdr-Environment_Variables"><code>GODEBUG=inittrace=1</code></a> prints execution time and memory allocation for all <code>init</code> calls, e.g. to analyze startup time regressions</li>
<li>See <a href="https://www.youtube.com/watch?v=pNd_BM0Tg4E">State of Go @ FOSDEM 2021</a> for another overview of the additions and changes coming with this release</li>
<li><span class="emoji" data-emoji="racing_car">🏎️</span> the <a href="https://tip.golang.org/doc/go1.16#linker">linker is faster</a>, requires less memory and binaries are getting smaller as a result of more aggressive symbol pruning¹</li>
<li>¹ my naïve explanation of symbol pruning:
<ul>
<li>a symbol contains metadata about the addresses of its variables and functions (<a href="http://nickdesaulniers.github.io/blog/2016/08/13/object-files-and-symbols/">source</a>)</li>
<li><span class="emoji" data-emoji="bulb">💡</span> you can show the symbols (symbol-table) of a binary using <code>nm <binary-file></code> (running <code>strip <binary-file></code> will remove them all)</li>
<li><em>symbol pruning</em> refers to the removal of symbols that are unused, e.g. uncalled functions from imported libraries</li>
</ul></li>
</ul>
<hr />
<h2 id="a-deeper-look-on-the-new-embed-package">A deeper look on the new <code>embed</code> package</h2>
<ul>
<li><a href="https://go-review.googlesource.com/c/go/+/243942">initial pull request</a> and <a href="https://go-review.googlesource.com/c/go/+/243945">go command support</a></li>
<li><a href="https://tip.golang.org/src/embed/embed.go">embed.go</a> is only 423 lines including comments and blank lines</li>
<li>strings are stored in plain-text in the binary</li>
<li>embedded files must be located inside the package (that imports <code>embed</code>) directory or its subdirectories</li>
<li>you can embed files as <code>string</code>, <code>[]byte</code> or <code>embed.FS</code>
<ul>
<li>use <code>embed.FS</code> when importing multiple (a tree of) files into a variable</li>
</ul></li>
<li>using the embed directive requires to import <code>embed</code> even when using <code>string</code> or <code>[]byte</code> variables (use blank import `import _ “embed”)</li>
<li><code>// go:embed pattern [pattern...]</code> where paths use <code>path.Match</code> patterns
<ul>
<li><code>string</code> and <code>[]byte</code> can only have a single pattern</li>
</ul></li>
<li>file patterns can be quoted like strings to embed paths containing spaces</li>
<li>directories are embedded recursively while paths beginning with _ or . are excluded
<ul>
<li>note that <code>// go:embed dir/*</code> will embed <code>dir/.foo</code> but <code>// go:embed dir</code> will not!</li>
</ul></li>
<li>patterns must not begin with ., .. or /</li>
<li>invalid patters and matches (e.g. a symbolic link) will cause the compilation to fail</li>
<li>embed directive can only be used with exported or unexported global variables at package scope</li>
<li>run example: <code>source .env && go run ./cmd/embed :12345</code></li>
<li>calling <code>strings</code> on the binary shows that content is embedded as plain-text</li>
</ul>
<h2 id="os-and-iofs"><code>os</code> and <code>io/fs</code></h2>
<ul>
<li>with <code>os.ReadDir</code>/<code>fs.ReadDir</code> we get to new functions for listing directory contents
<ul>
<li>those functions are a lot more efficient than <code>ioutil.ReadDir</code> because they do not require to call <code>stat</code> for each directory entry</li>
<li>for details see <a href="https://benhoyt.com/writings/go-readdir/">Ben Hoyts’ article</a></li>
<li>fun fact, those functions are inspired by <a href="https://docs.python.org/3/library/os.html#os.scandir">Python’s <code>os.scandir</code></a></li>
<li>to get the performance benefit of <code>ReadDir</code> when walking directory trees you need to use <a href="https://tip.golang.org/pkg/path/filepath/#WalkDir"><code>filepath.WalkDir</code></a> instead of <code>filepath.Walk</code>, <code>filepath.WalkDir</code> passes <code>fs.DirEntry</code> instead of <code>os.FileInfo</code> into the <code>WalkFn</code></li>
</ul></li>
</ul>
<div class="sourceCode" id="cb1"><pre class="sourceCode go"><code class="sourceCode go"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> FS <span class="kw">interface</span> {</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a> Open(name <span class="dt">string</span>) (File, <span class="dt">error</span>)</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
<ul>
<li><a href="https://tip.golang.org/pkg/io/fs/#FS"><code>io.FS</code></a> filesystem abstraction interface
<ul>
<li>prior art is <a href="https://github.com/spf13/afero"><code>afero</code></a> but it has a <a href="https://pkg.go.dev/github.com/spf13/afero#Fs">much larger interface</a> (and functionality, e.g. supports writes)</li>
<li><code>embed.FS</code> implements this so you can easily work with embedded directory trees</li>
<li>pretty useful for tests, e.g. to prevent side effects → <a href="https://tip.golang.org/pkg/testing/fstest/#MapFS"><code>testing/fstest.MapFS</code></a> is an in-memory file system</li>
<li>accept <code>fs.FS</code> and make your API filesystem agnostic, i.e. work transparently with a local directory, s3 block storage, remote file system etc.</li>
<li><span class="emoji" data-emoji="bulb">💡</span> you can easily test your custom file systems by passing them into <a href="https://tip.golang.org/pkg/testing/fstest/#TestFS"><code>fstest.TestFS</code></a></li>
</ul></li>
</ul>
<div class="sourceCode" id="cb2"><pre class="sourceCode go"><code class="sourceCode go"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> DeleteFS <span class="kw">interface</span> {</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a> FS</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a> Delete(name <span class="dt">string</span>) <span class="dt">error</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>}</span></code></pre></div>
<ul>
<li>if you need more functionality use interface composition to build a larger interface, take <a href="https://tip.golang.org/pkg/io/fs/#ReadDirFS">ReadDirFS</a> or <a href="https://tip.golang.org/pkg/io/fs/#ReadDirFS"><code>StatFS</code></a> as an example</li>
</ul>
<h2 id="generics">Generics</h2>
<p><a href="https://github.com/golang/go/issues/43651#issuecomment-776944155">The proposal got accepted</a> <span class="emoji" data-emoji="tada">🎉</span></p>
<ul>
<li>depending on your personal opinion this might be good or bad news</li>
<li>we will not see generics in a 1.x release</li>
<li><a href="https://www.ardanlabs.com/blog/2020/07/generics-01-basic-syntax.html">Ardan Labs three part blog article series about generics</a></li>
<li>(since some time already) there are two ways to try out generics:
<ol type="1">
<li>compile the <code>go2go</code> translation tool from the <code>dev.go2go</code> branch of the <a href="https://go.googlesource.com/go">Go repo</a> (<a href="https://go.googlesource.com/go/+/refs/heads/dev.go2go/README.go2go.md">instructions</a>)</li>
<li>use the <a href="https://go2goplay.golang.org/">go2go playgound</a></li>
</ol></li>
</ul>
<div class="sourceCode" id="cb3"><pre class="sourceCode go"><code class="sourceCode go"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">func</span> <span class="bu">print</span>[T any](value T) {</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a> fmt.Printf(<span class="st">"type=%T</span><span class="ch">\t</span><span class="st">value=%#v</span><span class="ch">\n</span><span class="st">"</span>, value, value)</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>}</span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="bu">print</span>([]<span class="dt">int</span>{<span class="dv">1</span>, <span class="dv">2</span>, <span class="dv">3</span>, <span class="dv">4</span>})</span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="bu">print</span>(<span class="st">"Hello, Golang Leipzig!"</span>)</span></code></pre></div>
<p><a href="https://go2goplay.golang.org/p/cGQWVpzboRI">playground</a></p>
<ul>
<li><code>[T any]</code> is the type parameter list
<ul>
<li><code>any</code> is a type <a href="https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-type-parameters.md#constraints"><em>constraint</em></a> (limiting the set of allowed types that can be used for <code>T</code>)</li>
<li><code>any</code> means “unconstrained” or allow any type for <code>T</code></li>
</ul></li>
</ul>
<div class="sourceCode" id="cb4"><pre class="sourceCode go"><code class="sourceCode go"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> Number <span class="kw">interface</span> {</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a> <span class="kw">type</span> <span class="dt">int</span>, <span class="dt">float64</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>}</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a><span class="kw">func</span> sum[T, S Number](a T, b S) S {</span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a> <span class="kw">return</span> S(a) + b</span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>}</span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>sum(<span class="dv">1</span>, <span class="dv">3</span><span class="fl">.1415</span>)</span></code></pre></div>
<p><a href="https://go2goplay.golang.org/p/JWm9mDpsvVf">playground</a></p>
<ul>
<li>a type parameter list can contain multiple type identifiers</li>
<li>… we will talk likely have a separate talk that covers Generics in depth</li>
</ul>
<h2 id="questions-question">Questions <span class="emoji" data-emoji="question">❓</span></h2>
</body>
</html>