-
Notifications
You must be signed in to change notification settings - Fork 1
/
go.html
137 lines (137 loc) · 37.1 KB
/
go.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
<!doctype html><html lang=en-uk><head><script data-goatcounter=https://ruivieira-dev.goatcounter.com/count async src=//gc.zgo.at/count.js></script><script src=https://unpkg.com/@alpinejs/intersect@3.x.x/dist/cdn.min.js></script><script src=https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js></script><script type=module src=https://ruivieira.dev/js/deeplinks/deeplinks.js></script><link rel=preload href=https://ruivieira.dev/lib/fonts/fa-brands-400.woff2 as=font type=font/woff2 crossorigin=anonymous><link rel=preload href=https://ruivieira.dev/lib/fonts/fa-regular-400.woff2 as=font type=font/woff2 crossorigin=anonymous><link rel=preload href=https://ruivieira.dev/lib/fonts/fa-solid-900.woff2 as=font type=font/woff2 crossorigin=anonymous><link rel=preload href=https://ruivieira.dev/fonts/firacode/FiraCode-Regular.woff2 as=font type=font/woff2 crossorigin=anonymous><link rel=preload href=https://ruivieira.dev/fonts/vollkorn/Vollkorn-Regular.woff2 as=font type=font/woff2 crossorigin=anonymous><link rel=stylesheet href=https://ruivieira.dev/css/kbd.css type=text/css><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><title>Go · Rui Vieira</title>
<link rel=canonical href=https://ruivieira.dev/go.html><meta name=viewport content="width=device-width,initial-scale=1"><meta name=robots content="all,follow"><meta name=googlebot content="index,follow,snippet,archive"><meta property="og:title" content="Go"><meta property="og:description" content="Some notes regarding the Go language. Some topics have graduated to their own page:
Go cookbook Go resource bundling Go filesystem operations SetupFirst things first. How to install the Go language in different OSes.
FedoraYou can either use dnf directly and simply run
$ sudo dnf install golang-bin This might not install the latest and greatest. If you want to use the most recent version, download it directly from https://golang.org/doc/install#install. If applicable, delete any previous /usr/local/go directory with"><meta property="og:type" content="article"><meta property="og:url" content="https://ruivieira.dev/go.html"><meta property="article:section" content="posts"><meta property="article:modified_time" content="2023-10-22T20:28:58+01:00"><meta name=twitter:card content="summary"><meta name=twitter:title content="Go"><meta name=twitter:description content="Some notes regarding the Go language. Some topics have graduated to their own page:
Go cookbook Go resource bundling Go filesystem operations SetupFirst things first. How to install the Go language in different OSes.
FedoraYou can either use dnf directly and simply run
$ sudo dnf install golang-bin This might not install the latest and greatest. If you want to use the most recent version, download it directly from https://golang.org/doc/install#install. If applicable, delete any previous /usr/local/go directory with"><link rel=stylesheet href=https://ruivieira.dev/css/styles.css><!--[if lt IE 9]><script src=https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js></script><script src=https://oss.maxcdn.com/respond/1.4.2/respond.min.js></script><![endif]--><link rel=icon type=image/png href=https://ruivieira.dev/images/favicon.ico></head><body class="max-width mx-auto px3 ltr" x-data="{currentHeading: undefined}"><div class="content index py4"><div id=header-post><a id=menu-icon href=#><i class="fas fa-eye fa-lg"></i></a>
<a id=menu-icon-tablet href=#><i class="fas fa-eye fa-lg"></i></a>
<a id=top-icon-tablet href=# onclick='$("html, body").animate({scrollTop:0},"fast")' style=display:none aria-label="Top of Page"><i class="fas fa-chevron-up fa-lg"></i></a>
<span id=menu><span id=nav><ul><li><a href=https://ruivieira.dev/>Home</a></li><li><a href=https://ruivieira.dev/blog/>Blog</a></li><li><a href=https://ruivieira.dev/draw/>Drawings</a></li><li><a href=https://ruivieira.dev/map/>All pages</a></li><li><a href=https://ruivieira.dev/search.html>Search</a></li></ul></span><br><div id=share style=display:none></div><div id=toc><h4>Contents</h4><nav id=TableOfContents><ul><li><a href=#setup :class="{'toc-h2':true, 'toc-highlight': currentHeading == '#setup' }">Setup</a></li><li><a href=#fedora :class="{'toc-h3':true, 'toc-highlight': currentHeading == '#fedora' }">Fedora</a></li><li><a href=#macos :class="{'toc-h3':true, 'toc-highlight': currentHeading == '#macos' }">macOS</a></li><li><a href=#language-design :class="{'toc-h2':true, 'toc-highlight': currentHeading == '#language-design' }">Language design</a></li><li><a href=#go-doesnt-have-sets :class="{'toc-h3':true, 'toc-highlight': currentHeading == '#go-doesnt-have-sets' }">Go doesn’t have sets</a></li><li><a href=#set-union :class="{'toc-h4':true, 'toc-highlight': currentHeading == '#set-union' }">Set union</a></li><li><a href=#set-intersection :class="{'toc-h4':true, 'toc-highlight': currentHeading == '#set-intersection' }">Set intersection</a></li><li><a href=#ci :class="{'toc-h3':true, 'toc-highlight': currentHeading == '#ci' }">CI</a></li><li><a href=#github :class="{'toc-h4':true, 'toc-highlight': currentHeading == '#github' }">GitHub</a></li><li><a href=#containers :class="{'toc-h3':true, 'toc-highlight': currentHeading == '#containers' }">Containers</a></li><li><a href=#minimal-example :class="{'toc-h4':true, 'toc-highlight': currentHeading == '#minimal-example' }">Minimal example</a></li><li><a href=#reference :class="{'toc-h3':true, 'toc-highlight': currentHeading == '#reference' }">Reference</a></li><li><a href=#conversions :class="{'toc-h4':true, 'toc-highlight': currentHeading == '#conversions' }">Conversions</a></li><li><a href=#collections :class="{'toc-h4':true, 'toc-highlight': currentHeading == '#collections' }">Collections</a></li><li><a href=#templates :class="{'toc-h4':true, 'toc-highlight': currentHeading == '#templates' }">Templates</a></li><li><a href=#processes :class="{'toc-h4':true, 'toc-highlight': currentHeading == '#processes' }">Processes</a></li><li><a href=#testing-in-go :class="{'toc-h4':true, 'toc-highlight': currentHeading == '#testing-in-go' }">Testing in Go</a></li><li><a href=#output :class="{'toc-h4':true, 'toc-highlight': currentHeading == '#output' }">Output</a></li><li><a href=#date-and-time :class="{'toc-h4':true, 'toc-highlight': currentHeading == '#date-and-time' }">Date and time</a></li></ul></nav><h4>Related</h4><nav><ul><li class="header-post toc"><span class=backlink-count>1</span>
<a href=https://ruivieira.dev/kubernetes.html>Kubernetes</a></li><li class="header-post toc"><span class=backlink-count>1</span>
<a href>Index</a></li><li class="header-post toc"><span class=backlink-count>1</span>
<a href=https://ruivieira.dev/from-scratch-to-emacs-the-adventurous-configurators-handbook.html>From Scratch to Emacs, The Adventurous Configurator's Handbook</a></li></ul></nav></div></span></div><article class=post itemscope itemtype=http://schema.org/BlogPosting><header><h1 class=posttitle itemprop="name headline">Go</h1><div class=meta><div class=postdate>Updated <time datetime="2023-10-22 20:28:58 +0100 BST" itemprop=datePublished>2023-10-22</time>
<span class=commit-hash>(<a href=https://ruivieira.dev/log/index.html#c4e6a85>c4e6a85</a>)</span></div></div></header><div class=content itemprop=articleBody><p>Some notes regarding the <a href=https://golang.org/>Go</a> language.
Some topics have graduated to their own page:</p><ul><li><a href>Go cookbook</a></li><li><a href=https://ruivieira.dev/go-resource-bundling.html>Go resource bundling</a></li><li><a href=https://ruivieira.dev/go-filesystem-operations.html>Go filesystem operations</a></li></ul><h2 id=setup x-intersect="currentHeading = '#setup'">Setup</h2><p>First things first. How to install the Go language in different OSes.</p><h3 id=fedora x-intersect="currentHeading = '#fedora'">Fedora</h3><p>You can either use <code>dnf</code> directly and simply run</p><div class=highlight><pre tabindex=0 style=background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-shell data-lang=shell><span style=display:flex><span>$ sudo dnf install golang-bin
</span></span></code></pre></div><p>This might not install the latest and greatest. If you want to use the most recent version, download it directly from <a href=https://golang.org/doc/install#install>https://golang.org/doc/install#install</a>.
If applicable, delete any previous <code>/usr/local/go</code> directory with</p><div class=highlight><pre tabindex=0 style=background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-shell data-lang=shell><span style=display:flex><span>$ sudo rm -rf /usr/local/go
</span></span></code></pre></div><p>Next, extract the archive file with</p><div class=highlight><pre tabindex=0 style=background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-shell data-lang=shell><span style=display:flex><span>$ sudo tar -C /usr/local -xzf /home/foo/tmp/go-<span style=color:teal>$VERSION</span>.linux-amd64.tar.gz
</span></span></code></pre></div><p>And add <code>/usr/local/go/bin</code> to the <code>$PATH</code>.</p><h3 id=macos x-intersect="currentHeading = '#macos'">macOS</h3><p>The best way to perform an <em>attended</em> installation of Go in macOS is to simply download the installer from <a href=https://go.dev/dl/>https://go.dev/dl/</a> and running it.</p><h2 id=language-design x-intersect="currentHeading = '#language-design'">Language design</h2><h3 id=go-doesnt-have-sets x-intersect="currentHeading = '#go-doesnt-have-sets'">Go doesn’t have sets</h3><p>The Go language, notoriously, does not have<sup id=fnref:1><a href=#fn:1 class=footnote-ref role=doc-noteref>1</a></sup> some common data structures like sets. There are two main reasons for that:</p><ol><li>+Go does not have generics<sup id=fnref:2><a href=#fn:2 class=footnote-ref role=doc-noteref>2</a></sup></li><li>Go relies on you writing your own data structures, generally</li></ol><p><del>Go lacks generics, which prevent writing a … well, generic and efficient set implementation.
Also, writing your own (non-generic) set with <code>map</code>s is quite straight-forward.</del><sup id=fnref1:2><a href=#fn:2 class=footnote-ref role=doc-noteref>2</a></sup>
The usual structure for a type <code>T</code> is <code>map[T]bool</code>, where the key is the element and the value is just a placeholder. For instance, for a <code>int</code> set, we can add elements:</p><div class=highlight><pre tabindex=0 style=background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span>s <span style=font-weight:700>:=</span> <span style=font-weight:700>map</span>[<span style=color:#458;font-weight:700>int</span>]<span style=color:#458;font-weight:700>bool</span>{<span style=color:#099>1</span>: <span style=font-weight:700>true</span>, <span style=color:#099>3</span>: <span style=font-weight:700>true</span>}
</span></span><span style=display:flex><span>s[<span style=color:#099>1</span>] = <span style=font-weight:700>true</span> <span style=color:#998;font-style:italic>// already presenvar t
</span></span></span><span style=display:flex><span><span style=color:#998;font-style:italic></span>s[<span style=color:#099>2</span>] = <span style=font-weight:700>true</span> <span style=color:#998;font-style:italic>// adds new element
</span></span></span></code></pre></div><p>Some other techniques for maps replacing sets:</p><h4 id=set-union x-intersect="currentHeading = '#set-union'">Set union</h4><div class=highlight><pre tabindex=0 style=background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span>set_1 <span style=font-weight:700>:=</span> <span style=font-weight:700>map</span>[<span style=color:#458;font-weight:700>int</span>]<span style=color:#458;font-weight:700>bool</span>{<span style=color:#099>1</span>:<span style=font-weight:700>true</span>, <span style=color:#099>2</span>:<span style=font-weight:700>true</span>, <span style=color:#099>3</span>:<span style=font-weight:700>false</span>}
</span></span><span style=display:flex><span>set_2 <span style=font-weight:700>:=</span> <span style=font-weight:700>map</span>[<span style=color:#458;font-weight:700>int</span>]<span style=color:#458;font-weight:700>bool</span>{<span style=color:#099>1</span>:<span style=font-weight:700>false</span>, <span style=color:#099>2</span>:<span style=font-weight:700>false</span>, <span style=color:#099>4</span>:<span style=font-weight:700>false</span>}
</span></span><span style=display:flex><span>set_union <span style=font-weight:700>:=</span> <span style=font-weight:700>map</span>[<span style=color:#458;font-weight:700>int</span>]<span style=color:#458;font-weight:700>bool</span>{}
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=font-weight:700>for</span> k, _ <span style=font-weight:700>:=</span> <span style=font-weight:700>range</span> set_1{
</span></span><span style=display:flex><span> set_union[k] = <span style=font-weight:700>true</span>
</span></span><span style=display:flex><span>}
</span></span><span style=display:flex><span><span style=font-weight:700>for</span> k, _ <span style=font-weight:700>:=</span> <span style=font-weight:700>range</span> set_2{
</span></span><span style=display:flex><span> set_union[k] = <span style=font-weight:700>true</span>
</span></span><span style=display:flex><span>}
</span></span><span style=display:flex><span>fmt.<span style=color:#900;font-weight:700>Println</span>(set_union)
</span></span></code></pre></div><h4 id=set-intersection x-intersect="currentHeading = '#set-intersection'">Set intersection</h4><div class=highlight><pre tabindex=0 style=background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span>set_1 <span style=font-weight:700>:=</span> <span style=font-weight:700>map</span>[<span style=color:#458;font-weight:700>int</span>]<span style=color:#458;font-weight:700>bool</span>{<span style=color:#099>1</span>:<span style=font-weight:700>true</span>, <span style=color:#099>2</span>:<span style=font-weight:700>true</span>, <span style=color:#099>3</span>:<span style=font-weight:700>false</span>}
</span></span><span style=display:flex><span>set_2 <span style=font-weight:700>:=</span> <span style=font-weight:700>map</span>[<span style=color:#458;font-weight:700>int</span>]<span style=color:#458;font-weight:700>bool</span>{<span style=color:#099>1</span>:<span style=font-weight:700>false</span>, <span style=color:#099>2</span>:<span style=font-weight:700>false</span>, <span style=color:#099>4</span>:<span style=font-weight:700>false</span>}
</span></span><span style=display:flex><span>set_intersection <span style=font-weight:700>:=</span> <span style=font-weight:700>map</span>[<span style=color:#458;font-weight:700>int</span>]<span style=color:#458;font-weight:700>bool</span>{}
</span></span><span style=display:flex><span><span style=font-weight:700>for</span> k,_ <span style=font-weight:700>:=</span> <span style=font-weight:700>range</span> set_1 {
</span></span><span style=display:flex><span> <span style=font-weight:700>if</span> set_2[k] {
</span></span><span style=display:flex><span> set_intersection[k] = <span style=font-weight:700>true</span>
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span><span style=display:flex><span>fmt.<span style=color:#900;font-weight:700>Println</span>(set_intersection)
</span></span></code></pre></div><p>To convert a (map) set to an array:</p><div class=highlight><pre tabindex=0 style=background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span>array <span style=font-weight:700>:=</span> <span style=color:#999>make</span>([]<span style=color:#458;font-weight:700>int</span>, <span style=color:#099>0</span>)
</span></span><span style=display:flex><span>set_1 <span style=font-weight:700>:=</span> <span style=font-weight:700>map</span>[<span style=color:#458;font-weight:700>int</span>]<span style=color:#458;font-weight:700>bool</span>{<span style=color:#099>1</span>:<span style=font-weight:700>true</span>, <span style=color:#099>2</span>:<span style=font-weight:700>true</span>, <span style=color:#099>3</span>:<span style=font-weight:700>false</span>}
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=font-weight:700>for</span> k <span style=font-weight:700>:=</span> <span style=font-weight:700>range</span> set_1 {
</span></span><span style=display:flex><span> array = <span style=color:#999>append</span>(array, k)
</span></span><span style=display:flex><span>}
</span></span><span style=display:flex><span>fmt.<span style=color:#900;font-weight:700>Println</span>(array)
</span></span></code></pre></div><h3 id=ci x-intersect="currentHeading = '#ci'">CI</h3><h4 id=github x-intersect="currentHeading = '#github'">GitHub</h4><p>A potential workflow for GitHub is to use <a href=https://github.com/mvdan/github-actions-golang>GitHub Actions for Go</a>.
An example workflow file, <code>.github/workflows/test.yml</code>, which runs <code>go test</code> (see <a href>Testing in Go</a>) and <code>go vet</code> is:</p><div class=highlight><pre tabindex=0 style=background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-yaml data-lang=yaml><span style=display:flex><span><span style=color:navy>on</span>:<span style=color:#bbb> </span>[push, pull_request\]<span style=color:#bbb>
</span></span></span><span style=display:flex><span><span style=color:#bbb></span><span style=color:navy>name</span>:<span style=color:#bbb> </span>Test<span style=color:#bbb>
</span></span></span><span style=display:flex><span><span style=color:#bbb></span><span style=color:navy>jobs</span>:<span style=color:#bbb>
</span></span></span><span style=display:flex><span><span style=color:#bbb> </span><span style=color:navy>test</span>:<span style=color:#bbb>
</span></span></span><span style=display:flex><span><span style=color:#bbb> </span><span style=color:navy>strategy</span>:<span style=color:#bbb>
</span></span></span><span style=display:flex><span><span style=color:#bbb> </span><span style=color:navy>matrix</span>:<span style=color:#bbb>
</span></span></span><span style=display:flex><span><span style=color:#bbb> </span><span style=color:navy>go-version</span>:<span style=color:#bbb> </span>[<span style=color:#099>1.14</span>.x, 1.15.x]<span style=color:#bbb>
</span></span></span><span style=display:flex><span><span style=color:#bbb> </span><span style=color:navy>os</span>:<span style=color:#bbb> </span>[ubuntu-latest]<span style=color:#bbb>
</span></span></span><span style=display:flex><span><span style=color:#bbb> </span><span style=color:navy>runs-on</span>:<span style=color:#bbb> </span>${{ matrix.os }}<span style=color:#bbb>
</span></span></span><span style=display:flex><span><span style=color:#bbb> </span><span style=color:navy>steps</span>:<span style=color:#bbb>
</span></span></span><span style=display:flex><span><span style=color:#bbb> </span>- <span style=color:navy>name</span>:<span style=color:#bbb> </span>Install Go<span style=color:#bbb>
</span></span></span><span style=display:flex><span><span style=color:#bbb> </span><span style=color:navy>uses</span>:<span style=color:#bbb> </span>actions/setup-go@v2<span style=color:#bbb>
</span></span></span><span style=display:flex><span><span style=color:#bbb> </span><span style=color:navy>with</span>:<span style=color:#bbb>
</span></span></span><span style=display:flex><span><span style=color:#bbb> </span><span style=color:navy>go-version</span>:<span style=color:#bbb> </span>${{ matrix.go-version }}<span style=color:#bbb>
</span></span></span><span style=display:flex><span><span style=color:#bbb> </span>- <span style=color:navy>name</span>:<span style=color:#bbb> </span>Checkout code<span style=color:#bbb>
</span></span></span><span style=display:flex><span><span style=color:#bbb> </span><span style=color:navy>uses</span>:<span style=color:#bbb> </span>actions/checkout@v2<span style=color:#bbb>
</span></span></span><span style=display:flex><span><span style=color:#bbb> </span>- <span style=color:navy>name</span>:<span style=color:#bbb> </span>Test<span style=color:#bbb>
</span></span></span><span style=display:flex><span><span style=color:#bbb> </span><span style=color:navy>run</span>:<span style=color:#bbb> </span>go test ./...<span style=color:#bbb>
</span></span></span><span style=display:flex><span><span style=color:#bbb> </span>- <span style=color:navy>name</span>:<span style=color:#bbb> </span>Vet<span style=color:#bbb>
</span></span></span><span style=display:flex><span><span style=color:#bbb> </span><span style=color:navy>run</span>:<span style=color:#bbb> </span>go vet ./...<span style=color:#bbb>
</span></span></span></code></pre></div><h3 id=containers x-intersect="currentHeading = '#containers'">Containers</h3><h4 id=minimal-example x-intersect="currentHeading = '#minimal-example'">Minimal example</h4><p>A minimal example of a Go <a href=https://ruivieira.dev/containers.html>container</a> configuration for a web server running on port <code>8080</code>:</p><div class=highlight><pre tabindex=0 style=background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-Dockerfile data-lang=Dockerfile><span style=display:flex><span><span style=color:#998;font-style:italic># Start from the latest golang base image </span><span style=color:#a61717;background-color:#e3d2d2>
</span></span></span><span style=display:flex><span><span style=color:#a61717;background-color:#e3d2d2></span><span style=font-weight:700>FROM</span><span style=color:#b84> golang:latest </span><span style=color:#a61717;background-color:#e3d2d2>
</span></span></span><span style=display:flex><span><span style=color:#a61717;background-color:#e3d2d2></span><span style=color:#998;font-style:italic># Add Maintainer Info </span><span style=color:#a61717;background-color:#e3d2d2>
</span></span></span><span style=display:flex><span><span style=color:#a61717;background-color:#e3d2d2></span><span style=font-weight:700>LABEL</span> <span style=color:teal>maintainer</span><span style=font-weight:700>=</span><span style=color:#b84>"Rui Vieira"</span> <span style=color:#a61717;background-color:#e3d2d2>
</span></span></span><span style=display:flex><span><span style=color:#a61717;background-color:#e3d2d2></span><span style=color:#998;font-style:italic># Set the Current Working Directory inside the container </span><span style=color:#a61717;background-color:#e3d2d2>
</span></span></span><span style=display:flex><span><span style=color:#a61717;background-color:#e3d2d2></span><span style=font-weight:700>WORKDIR</span><span style=color:#b84> /app </span><span style=color:#a61717;background-color:#e3d2d2>
</span></span></span><span style=display:flex><span><span style=color:#a61717;background-color:#e3d2d2></span><span style=color:#998;font-style:italic># Copy go mod and sum files </span><span style=color:#a61717;background-color:#e3d2d2>
</span></span></span><span style=display:flex><span><span style=color:#a61717;background-color:#e3d2d2></span><span style=font-weight:700>COPY</span> go.mod go.sum ./ <span style=color:#a61717;background-color:#e3d2d2>
</span></span></span><span style=display:flex><span><span style=color:#a61717;background-color:#e3d2d2></span><span style=color:#998;font-style:italic># Download all dependencies. Dependencies will be cached if the go.mod and go.sum files are not changed </span><span style=color:#a61717;background-color:#e3d2d2>
</span></span></span><span style=display:flex><span><span style=color:#a61717;background-color:#e3d2d2></span><span style=font-weight:700>RUN</span> go mod download <span style=color:#a61717;background-color:#e3d2d2>
</span></span></span><span style=display:flex><span><span style=color:#a61717;background-color:#e3d2d2></span><span style=color:#998;font-style:italic># Copy the source from the current directory to the Working Directory inside the container </span><span style=color:#a61717;background-color:#e3d2d2>
</span></span></span><span style=display:flex><span><span style=color:#a61717;background-color:#e3d2d2></span><span style=font-weight:700>COPY</span> . . <span style=color:#a61717;background-color:#e3d2d2>
</span></span></span><span style=display:flex><span><span style=color:#a61717;background-color:#e3d2d2></span><span style=color:#998;font-style:italic># Build the Go app </span><span style=color:#a61717;background-color:#e3d2d2>
</span></span></span><span style=display:flex><span><span style=color:#a61717;background-color:#e3d2d2></span><span style=font-weight:700>RUN</span> go build -o main . <span style=color:#a61717;background-color:#e3d2d2>
</span></span></span><span style=display:flex><span><span style=color:#a61717;background-color:#e3d2d2></span><span style=color:#998;font-style:italic># Expose port 8080 to the outside world </span><span style=color:#a61717;background-color:#e3d2d2>
</span></span></span><span style=display:flex><span><span style=color:#a61717;background-color:#e3d2d2></span><span style=font-weight:700>EXPOSE</span><span style=color:#b84> 8080 </span><span style=color:#a61717;background-color:#e3d2d2>
</span></span></span><span style=display:flex><span><span style=color:#a61717;background-color:#e3d2d2></span><span style=color:#998;font-style:italic># Command to run the executable </span><span style=color:#a61717;background-color:#e3d2d2>
</span></span></span><span style=display:flex><span><span style=color:#a61717;background-color:#e3d2d2></span><span style=font-weight:700>CMD</span> [<span style=color:#b84>"./main"</span>]<span style=color:#a61717;background-color:#e3d2d2>
</span></span></span></code></pre></div><h3 id=reference x-intersect="currentHeading = '#reference'">Reference</h3><h4 id=conversions x-intersect="currentHeading = '#conversions'">Conversions</h4><h5 id=how-to-convert-a-string-to-byte-array x-intersect="currentHeading = '#how-to-convert-a-string-to-byte-array'">How to convert a <code>string</code> to <code>byte</code> array?</h5><p>The conversion is simple:</p><div class=highlight><pre tabindex=0 style=background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span> b <span style=font-weight:700>:=</span> []<span style=color:#999>byte</span>(<span style=color:#b84>"This is a string"</span>)
</span></span></code></pre></div><h4 id=collections x-intersect="currentHeading = '#collections'">Collections</h4><h5 id=sort-map-keys-alphabetically x-intersect="currentHeading = '#sort-map-keys-alphabetically'">Sort map keys alphabetically</h5><p>If a <code>map</code> contains <code>string</code> keys, <em>i.e.</em> <code>var myMap map[string]T</code>, we must sort the map keys independently. For instance:</p><div class=highlight><pre tabindex=0 style=background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span>keys <span style=font-weight:700>:=</span> <span style=color:#999>make</span>([]<span style=color:#458;font-weight:700>string</span>, <span style=color:#099>0</span>)
</span></span><span style=display:flex><span><span style=font-weight:700>for</span> k, _ <span style=font-weight:700>:=</span> <span style=font-weight:700>range</span> myMap {
</span></span><span style=display:flex><span> keys = <span style=color:#999>append</span>(keys, k)
</span></span><span style=display:flex><span>}
</span></span><span style=display:flex><span>sort.<span style=color:#900;font-weight:700>Strings</span>(keys)
</span></span><span style=display:flex><span><span style=font-weight:700>for</span> _, k <span style=font-weight:700>:=</span> <span style=font-weight:700>range</span> keys {
</span></span><span style=display:flex><span> fmt.<span style=color:#900;font-weight:700>Println</span>(k, myMap[k])
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><h5 id=check-for-element x-intersect="currentHeading = '#check-for-element'">Check for element</h5><p>If we consider a collection, say, <code>[]string collection</code>, the way to check for an element already present is, for instance:</p><div class=highlight><pre tabindex=0 style=background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=font-weight:700>func</span> <span style=color:#900;font-weight:700>existsIn</span>(needle <span style=color:#458;font-weight:700>string</span>, haystack []<span style=color:#458;font-weight:700>string</span>) <span style=color:#458;font-weight:700>bool</span> {
</span></span><span style=display:flex><span> <span style=font-weight:700>for</span> _, element <span style=font-weight:700>:=</span> <span style=font-weight:700>range</span> haystack {
</span></span><span style=display:flex><span> <span style=font-weight:700>if</span> element <span style=font-weight:700>==</span> needle {
</span></span><span style=display:flex><span> <span style=font-weight:700>return</span> <span style=font-weight:700>true</span>
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> <span style=font-weight:700>return</span> <span style=font-weight:700>false</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><h4 id=templates x-intersect="currentHeading = '#templates'">Templates</h4><h5 id=check-if-variable-empty x-intersect="currentHeading = '#check-if-variable-empty'">Check if variable empty</h5><p>In a Go template you check if a variable is empty by doing:</p><div class=highlight><pre tabindex=0 style=background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-html data-lang=html><span style=display:flex><span>{{if .Items}}
</span></span><span style=display:flex><span><<span style=color:navy>ul</span>>
</span></span><span style=display:flex><span> {{range .Items}}
</span></span><span style=display:flex><span> <<span style=color:navy>li</span>>{{.Name}}</<span style=color:navy>li</span>>
</span></span><span style=display:flex><span> {{end}}
</span></span><span style=display:flex><span></<span style=color:navy>ul</span>>
</span></span><span style=display:flex><span>{{end}}
</span></span></code></pre></div><h5 id=looping-over-a-map x-intersect="currentHeading = '#looping-over-a-map'">Looping over a map</h5><p>Looping over the map <code>var data map[string]bool</code> in a Go template:</p><div class=highlight><pre tabindex=0 style=background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-html data-lang=html><span style=display:flex><span>{{range $index, $element := .}}
</span></span><span style=display:flex><span> {{$index}}: {{$element}}
</span></span><span style=display:flex><span>{{end}}
</span></span></code></pre></div><h4 id=processes x-intersect="currentHeading = '#processes'">Processes</h4><h5 id=executing-external-processes x-intersect="currentHeading = '#executing-external-processes'">Executing external processes</h5><p>Executing an external process and directing input and output to <code>Stdout</code> and <code>Stderr</code>.</p><div class=highlight><pre tabindex=0 style=background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span> cmd <span style=font-weight:700>:=</span> exec.<span style=color:#900;font-weight:700>Command</span>(<span style=color:#b84>"ls"</span>, <span style=color:#b84>"-1ao"</span>)
</span></span><span style=display:flex><span> cmd.Stdout = os.Stdout
</span></span><span style=display:flex><span> cmd.Stderr = os.Stderr
</span></span><span style=display:flex><span> err <span style=font-weight:700>:=</span> cmd.<span style=color:#900;font-weight:700>Run</span>()
</span></span><span style=display:flex><span> <span style=font-weight:700>if</span> err <span style=font-weight:700>!=</span> <span style=font-weight:700>nil</span> {
</span></span><span style=display:flex><span> log.<span style=color:#900;font-weight:700>Fatalf</span>(<span style=color:#b84>"cmd.Run() failed with %s\\n"</span>, err)
</span></span><span style=display:flex><span> }
</span></span></code></pre></div><h4 id=testing-in-go x-intersect="currentHeading = '#testing-in-go'">Testing in Go</h4><p>Place the tests in your place of choosing, but keep the package declaration. Test functions should be parameterised as <code>(t *testing.T)</code> and start with the prefix <code>Test</code>, for instance:</p><div class=highlight><pre tabindex=0 style=background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span><span style=font-weight:700>package</span> main
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=font-weight:700>func</span> <span style=color:#900;font-weight:700>TestFoo</span>(t <span style=font-weight:700>*</span>testing.T) {
</span></span><span style=display:flex><span> value <span style=font-weight:700>:=</span> <span style=color:#900;font-weight:700>Foo</span>(<span style=color:#099>5</span>, <span style=color:#099>5</span>)
</span></span><span style=display:flex><span> <span style=color:#998;font-style:italic>// ... assertions
</span></span></span></code></pre></div><p>The test files themselves must have the suffix <code>*_test.go</code>.
Call the tests with <code>go test</code>.</p><h4 id=output x-intersect="currentHeading = '#output'">Output</h4><h5 id=printing-struct-keys x-intersect="currentHeading = '#printing-struct-keys'">Printing struct keys</h5><p>To print a <code>struct</code> along with its keys, we can use the <code>Printf</code> switch as in the <a href=https://golang.org/pkg/fmt/#hdr-Printing>official documentation</a>. That is,</p><div class=highlight><pre tabindex=0 style=background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span>fmt.<span style=color:#900;font-weight:700>Printf</span>(<span style=color:#b84>"%+v\n"</span>, myStruct)
</span></span></code></pre></div><h4 id=date-and-time x-intersect="currentHeading = '#date-and-time'">Date and time</h4><h5 id=check-if-a-date-is-empty x-intersect="currentHeading = '#check-if-a-date-is-empty'">Check if a date is empty</h5><p>If a date is unassigned, the <code>.IsZero()</code> method can be used to check it</p><div class=highlight><pre tabindex=0 style=background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-go data-lang=go><span style=display:flex><span>a <span style=font-weight:700>:=</span> time.Time{}
</span></span><span style=display:flex><span>a.<span style=color:#900;font-weight:700>IsZero</span>() <span style=color:#998;font-style:italic>// This will be true
</span></span></span></code></pre></div><div class=footnotes role=doc-endnotes><hr><ol><li id=fn:1><p>As of the time of writing, that is Go 1.15. <a href=#fnref:1 class=footnote-backref role=doc-backlink>↩︎</a></p></li><li id=fn:2><p>Go indeed has generics starting with 1.18. <a href=#fnref:2 class=footnote-backref role=doc-backlink>↩︎</a> <a href=#fnref1:2 class=footnote-backref role=doc-backlink>↩︎</a></p></li></ol></div></div></article><div id=footer-post-container><div id=footer-post><div id=nav-footer style=display:none><ul><li><a href=https://ruivieira.dev/>Home</a></li><li><a href=https://ruivieira.dev/blog/>Blog</a></li><li><a href=https://ruivieira.dev/draw/>Drawings</a></li><li><a href=https://ruivieira.dev/map/>All pages</a></li><li><a href=https://ruivieira.dev/search.html>Search</a></li></ul></div><div id=toc-footer style=display:none><nav id=TableOfContents><ul><li><a href=#setup>Setup</a><ul><li><a href=#fedora>Fedora</a></li><li><a href=#macos>macOS</a></li></ul></li><li><a href=#language-design>Language design</a><ul><li><a href=#go-doesnt-have-sets>Go doesn’t have sets</a></li><li><a href=#ci>CI</a></li><li><a href=#containers>Containers</a></li><li><a href=#reference>Reference</a></li></ul></li></ul></nav></div><div id=share-footer style=display:none></div><div id=actions-footer><a id=menu-toggle class=icon href=# onclick='return $("#nav-footer").toggle(),!1' aria-label=Menu><i class="fas fa-bars fa-lg" aria-hidden=true></i> Menu</a>
<a id=toc-toggle class=icon href=# onclick='return $("#toc-footer").toggle(),!1' aria-label=TOC><i class="fas fa-list fa-lg" aria-hidden=true></i> TOC</a>
<a id=share-toggle class=icon href=# onclick='return $("#share-footer").toggle(),!1' aria-label=Share><i class="fas fa-share-alt fa-lg" aria-hidden=true></i> share</a>
<a id=top style=display:none class=icon href=# onclick='$("html, body").animate({scrollTop:0},"fast")' aria-label="Top of Page"><i class="fas fa-chevron-up fa-lg" aria-hidden=true></i> Top</a></div></div></div><footer id=footer><div class=footer-left>Copyright © 2024 Rui Vieira</div><div class=footer-right><nav><ul><li><a href=https://ruivieira.dev/>Home</a></li><li><a href=https://ruivieira.dev/blog/>Blog</a></li><li><a href=https://ruivieira.dev/draw/>Drawings</a></li><li><a href=https://ruivieira.dev/map/>All pages</a></li><li><a href=https://ruivieira.dev/search.html>Search</a></li></ul></nav></div></footer></div></body><link rel=stylesheet href=https://ruivieira.dev/css/fa.min.css><script src=https://ruivieira.dev/js/jquery-3.6.0.min.js></script><script src=https://ruivieira.dev/js/mark.min.js></script><script src=https://ruivieira.dev/js/main.js></script></html>