Open13

A Tour of Go やってみた

kazu_kichi_67kazu_kichi_67

Hello, 世界

Macのセットアップは以下を参照
https://qiita.com/yoshihiro-kato/items/14e3fd701c63ee9a088a

リポジトリは以下、
https://github.com/kazu-kichi-67/A-Tour-of-Go-practice

% go version
go version go1.23.4 darwin/arm64

ん?

% go tool tour
go: no such tool "tour"

https://qiita.com/okaponta_/items/50ab02605a5f3b6bf5bd
英語版のコマンドを見てみるといいらしい。

% go install golang.org/x/website/tour@latest
go: downloading golang.org/x/website/tour v0.0.0-20210616181959-e0d934b43647
go: downloading golang.org/x/website v0.0.0-20241223144644-abd320122603
go: downloading golang.org/x/tools v0.1.3-0.20210525215409-a3eb095d6aee
go: downloading golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4
go: downloading golang.org/x/mod v0.4.2
go: downloading golang.org/x/sys v0.0.0-20210510120138-977fb7262007
go: downloading github.com/yuin/goldmark v1.3.5
go: downloading golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1

んーよくわからないけど、進めてみる。

% ~/go/bin/tour           
2024/12/26 16:03:19 Serving content from /Users/kazukichi/go/pkg/mod/golang.org/x/website/tour@v0.0.0-20210616181959-e0d934b43647
2024/12/26 16:03:19 A browser window should open. If not, please visit http://127.0.0.1:3999
2024/12/26 16:03:19 accepting connection from: 127.0.0.1:62193

http://127.0.0.1:3999/welcome/1
が立ち上がってローカルでA Tour of Goが出来るみたい。

ローカルで普通に開発できるのかと思ったけど、思ってたんと違ったw

kazu_kichi_67kazu_kichi_67

蛇足)

ひとまずhello.goを作って動かしてみる。

VSCodeのextentionも追加。

% go run 1-Welcome/hello.go 
Hello, 世界
% go run 1-Welcome/sandbox.go 
Welcome to the playground!
The time is 2024-12-26 16:17:31.793507 +0900 JST m=+0.000168168

OK

kazu_kichi_67kazu_kichi_67

Packages

https://go-tour-jp.appspot.com/basics/1

% go run 2-Packages-variables-and-functions/packages.go
My favorite number is 2
% go run 2-Packages-variables-and-functions/packages.go
My favorite number is 1
% go run 2-Packages-variables-and-functions/packages.go
My favorite number is 9

Note: ここで実行するプログラムは常に同じ環境で実行されます ので、擬似乱数を返す rand.Intn はいつも同じ数を返します。

(数を強制的に変える場合は、乱数生成でシードを与える必要があります。rand.Seedを見てみてください。 playground 上での時間は一定なので他のものをシードとして使う必要があります。)

ここがよくわからない・・
ローカルでもweb上でもちゃんと乱数生成できてるけどな。。

https://go.dev/tour/basics/1
英語版にはそのような表記なし。

もしかして日本語版、結構怪しい感じ??

kazu_kichi_67kazu_kichi_67

Imports

importはまとめるのがお作法。

% go run 2-Packages-variables-and-functions/imports.go
Now you have 2.6457513110645907 problems.

平方根を求めるやつ
https://pkg.go.dev/math#Sqrt

Exported names

% go run 2-Packages-variables-and-functions/exported-names.go 
# command-line-arguments
2-Packages-variables-and-functions/exported-names.go:8:14: undefined: math

Piに変える。

% go run 2-Packages-variables-and-functions/exported-names.go
3.141592653589793

Piって円周率か。

const.goに定数定義されてた

// Mathematical constants.
const (
	E   = 2.71828182845904523536028747135266249775724709369995957496696763 // https://oeis.org/A001113
	Pi  = 3.14159265358979323846264338327950288419716939937510582097494459 // https://oeis.org/A000796
	Phi = 1.61803398874989484820458683436563811772030917980576286213544862 // https://oeis.org/A001622

	Sqrt2   = 1.41421356237309504880168872420969807856967187537694807317667974 // https://oeis.org/A002193
	SqrtE   = 1.64872127070012814684865078781416357165377610071014801157507931 // https://oeis.org/A019774
	SqrtPi  = 1.77245385090551602729816748334114518279754945612238712821380779 // https://oeis.org/A002161
	SqrtPhi = 1.27201964951406896425242246173749149171560804184009624861664038 // https://oeis.org/A139339

	Ln2    = 0.693147180559945309417232121458176568075500134360255254120680009 // https://oeis.org/A002162
	Log2E  = 1 / Ln2
	Ln10   = 2.30258509299404568401799145468436420760110148862877297603332790 // https://oeis.org/A002392
	Log10E = 1 / Ln10
)
kazu_kichi_67kazu_kichi_67

Functions

型定義は後ろ。

% go run 2-Packages-variables-and-functions/functions.go
55

構文に込められた思い
https://go.dev/blog/declaration-syntax

ポインタがあるのか。C++以来でドキドキ。

Functions continued

同じ型の変数は省略可能。

Multiple results

標準で複数returnできるのアツい!

(javaだと自前で入れ物作るか、Pairとか使わないといけなかった・・)

% go run 2-Packages-variables-and-functions/multiple-results.go 
world hello

Named return values

関数定義でreturn 対象変数を宣言することができる、が、多用すると可読性落ちると。

% go run 2-Packages-variables-and-functions/named-results.go   
7 10

Variables

変数宣言。一応調べたけど、valは存在しないと。
final もないっぽいけど、もしや再代入防ぐのちょいめんどい??

% go run 2-Packages-variables-and-functions/variables.go
0 false false false

基本final付けたいマン、基本immutableにしたいマンなので、ちょっと調べてみたら、
以下が参考になった。

https://zenn.dev/nobonobo/articles/9a9f12b27bfde9
https://zenn.dev/hirochon/articles/499a3a321c858d

イミュータブル修飾が効率的に機能するには関数型言語としての最適化機能もなければ片手落ち

くっ・・耳が痛い。。

Variables with initializers

var c, python, java = true, false, "no!"

んー、これは慣れないと読みづらいw

% go run 2-Packages-variables-and-functions/variables-with-initializers.go 
1 2 true false no!

Short variable declarations

var は := で代替可能。
1文字しか減ってない気もするけど・・
プロジェクト毎にどっちで定義するってコーディング規約は作られる感じかな

% go run 2-Packages-variables-and-functions/short-variable-declarations.go 
1 2 3 true false no!
kazu_kichi_67kazu_kichi_67

Basic types

基本型(組み込み型)について。

import同様、varもまとめて宣言可能。

「<<」「>>」はビット演算子。(いきなり出すのズルない?w)

https://qiita.com/KenAra/items/bf19fb94c93f7f28396e

complexは複素数。
複素数の平方根ってことでいいのかな。なんか例がムズいんだがw

http://www.nct9.ne.jp/m_hiroi/golang/abcgo31.html
https://pkg.go.dev/math/cmplx#Sqrt

% go run 2-Packages-variables-and-functions/basic-types.go                
Type: bool Value: false
Type: uint64 Value: 18446744073709551615
Type: complex128 Value: (2+3i)

%Tでtype出力できるのいいね

Zero values

暗黙の初期値。
特に違和感ないけど、書式指定子がわからんので調べる。

https://qiita.com/ken/items/2c0cc33bb8edf8b8160f

% go run 2-Packages-variables-and-functions/zero.go       
0 0 false ""

Type conversions

暗黙のキャストはない。

% go run 2-Packages-variables-and-functions/type-conversions.go 
3 4 5

明示的に書かなければエラー。

% go run 2-Packages-variables-and-functions/type-conversions.go
# command-line-arguments
2-Packages-variables-and-functions/type-conversions.go:12:15: cannot use f (variable of type float64) as uint value in variable declaration

Type inference

右辺に合わせて型推論してくれる。

% go run 2-Packages-variables-and-functions/type-inference.go  
v is of type int
i := 42           // int
f := 3.142        // float64
g := 0.867 + 0.5i // complex128

Constants

定数定義。

% go run 2-Packages-variables-and-functions/constants.go     
Hello 世界
Happy 3.14 Day
Go rules? true

定数は、文字(character)、文字列(string)、boolean、数値(numeric)のみ

Numeric Constants

constも型省略可能で、変数同様に推論される。

% go run 2-Packages-variables-and-functions/numeric-constants.go 
21
0.2
1.2676506002282295e+29
kazu_kichi_67kazu_kichi_67

For

% go run 3-Flow-control-statements/for.go                       
45

For continued

% go run 3-Flow-control-statements/for-continued.go
1
2
4
8
16
32
64
128
256
512
1024

For is Go's "while"

whileと同じように書ける

Forever

条件を書かなければ無限ループになる

If

% go run 3-Flow-control-statements/if.go           
1.4142135623730951 2i

If with a short statement

Powはべき乗

% go run 3-Flow-control-statements/if-with-a-short-statement.go 
9 20

If and else

% go run 3-Flow-control-statements/if-and-else.go              
27 >= 20
9 20

Exercise: Loops and Functions

copilot有効のままになってて、一瞬で答え書かれた・・

% go run 3-Flow-control-statements/exercise-loops-and-functions.go 
1.4142135623730951
kazu_kichi_67kazu_kichi_67

Switch

% go run 3-Flow-control-statements/switch.go                      
Go runs on OS X.

Switch evaluation order

% go run 3-Flow-control-statements/switch-evaluation-order.go 
When's Saturday?
Today.

Switch with no condition

なんこれ、オシャレじゃん・・

% go run 3-Flow-control-statements/switch-with-no-condition.go 
Good afternoon.

Defer

急にちょっとクセあるやつキタ・・
実際の業務でどのくらい使われるのか気になる。。

% go run 3-Flow-control-statements/defer.go 
hello
world

Stacking defers

LIFOなのか!

https://go.dev/blog/defer-panic-and-recover
→ ファイルIOを必ず閉じるように使ったりするっぽい。
try-with-resourcesみたいなものはなくて、これ使う感じかな。

% go run 3-Flow-control-statements/defer-multi.go 
counting
done
9
8
7
6
5
4
3
2
1
0
kazu_kichi_67kazu_kichi_67

Pointers

% go run 4-More-types/pointers.go
42
21
73

Structs

% go run 4-More-types/structs.go 
{1 2}

Struct Fields

% go run 4-More-types/struct-fields.go 
4

Pointers to structs

% go run 4-More-types/struct-pointers.go 
{1000000000 2}

Struct Literals

% go run 4-More-types/struct-literals.go 
{1 2} &{1 2} {1 0} {0 0}

Arrays

% go run 4-More-types/array.go          
Hello World
[Hello World]
[2 3 5 7 11 13]

Slices

% go run 4-More-types/slices.go 
[3 5 7]

Slices are like references to arrays

スライスは配列への参照のようなもの

% go run 4-More-types/slices-pointers.go 
[John Paul George Ringo]
[John Paul] [Paul George]
[John XXX] [XXX George]
[John XXX George Ringo]

Slice literals

% go run 4-More-types/slice-literals.go 
[2 3 5 7 11 13]
[true false true true false true]
[{2 true} {3 false} {5 true} {7 true} {11 false} {13 true}]

Slice defaults

% go run 4-More-types/slice-bounds.go  
[3 5 7]
[3 5]
[5]

Slice length and capacity

% go run 4-More-types/slice-len-cap.go 
len=6 cap=6 [2 3 5 7 11 13]
len=0 cap=6 []
len=4 cap=6 [2 3 5 7]
len=2 cap=4 [5 7]

え、、急にむずい・・w

参考:
https://zenn.dev/sryoya/articles/6a8ae7daa20aa7

Nil slices

% go run 4-More-types/nil-slices.go   
[] 0 0
nil!
kazu_kichi_67kazu_kichi_67

Creating a slice with make

% go run 4-More-types/making-slices.go 
a len=5 cap=5 [0 0 0 0 0]
b len=0 cap=5 []
c len=2 cap=5 [0 0]
d len=3 cap=3 [0 0 0]

Slices of slices

% go run 4-More-types/slices-of-slice.go 
X _ X
O _ X
_ _ O

Appending to a slice

% go run 4-More-types/append.go         
len=0 cap=0 []
len=1 cap=1 [0]
len=2 cap=2 [0 1]
len=5 cap=6 [0 1 2 3 4]

https://go.dev/blog/slices-intro

Range

% go run 4-More-types/range.go 
2**0 = 1
2**1 = 2
2**2 = 4
2**3 = 8
2**4 = 16
2**5 = 32
2**6 = 64
2**7 = 128

Range continued

% go run 4-More-types/range-continued.go 
1
2
4
8
16
32
64
128
256
512

Exercise: Slices

% go run 4-More-types/exercise/exercise-slices.go 
4-More-types/exercise/exercise-slices.go:3:8: no required module provides package golang.org/x/tour/pic: go.mod file not found in current directory or any parent directory; see 'go help modules'

import "golang.org/x/tour/pic"

がうまく取れていない模様。

公式:
https://go.dev/doc/tutorial/create-module

解説助かる。
https://qiita.com/okaponta_/items/d9e607e39f223500c51e

モジュール初期化

% go mod init exercise
go: creating new go.mod: module exercise
go: to add module requirements and sums:
        go mod tidy

再度実行。

% go run exercise-slices.go 
exercise-slices.go:3:8: no required module provides package golang.org/x/tour/pic; to add it:
        go get golang.org/x/tour/pic

言われるがまま。

% go get golang.org/x/tour/pic
go: downloading golang.org/x/tour v0.1.0
go: added golang.org/x/tour v0.1.0

go.sumファイルができたみたい

% go run exercise-slices.go   
# command-line-arguments
./exercise-slices.go:7:1: missing return

importのエラーは解消した模様。

% go run exercise-slices.go
IMAGE:iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAIAAADTED8xAAACaUlEQVR42uzVMRGAAAzAwLSHf8tgAAf95QVkyVNvNRN50FWBl10V6ABa0AFIByAdgHQA0gFIByAdgHQA0gFIByAdgHQA0gFIByAdgHQA0gFIByAdgHQA0gFIByAdgHQA0gFIByAdgHQA0gFIByAdgHQA0gFIByAdgHQA0gFIByAdgHQA0gFIByAdgHQA0gFIByAdgHQA0gFIB6ADqEAHIB2AdADSAUgHIB2AdADSAUgHIB2AdADSAUgHIB2AdADSAUgHIB2AdADSAUgHIB2AdADSAUgHIB2AdADSAUgHIB2AdADSAUgHIB2AdADSAUgHIB2AdADSAUgHIB2AdADSAUgHIB2AdADSAUgHIB2AdAA6gBZ0ANIBSAcgHYB0ANIBSAcgHYB0ANIBSAcgHYB0ANIBSAcgHYB0ANIBSAcgHYB0ANIBSAcgHYB0ANIBSAcgHYB0ANIBSAcgHYB0ANIBSAcgHYB0ANIBSAcgHYB0ANIBSAcgHYB0ANIBSAcgHYB0ANIB6AAq0AFIByAdgHQA0gFIByAdgHQA0gFIByAdgHQA0gFIByAdgHQA0gFIByAdgHQA0gFIByAdgHQA0gFIByAdgHQA0gFIByAdgHQA0gFIByAdgHQA0gFIByAdgHQA0gFIByAdgHQA0gFIByAdgHQA0gFIByAdgA6gAh2AdADSAUgHIB2AdADSAUgHIB2AdADSAUgHIB2AdADSAUgHIB2AdADSAUgHIB2AdADSAUgHIB2AdADSAUgHIB2AdADSAUgHIB2AdADSAUgHIB2AdADSAUgHIB2AdADSAUgHIB2AdADyxy8AAP//YSoDD5pLB7MAAAAASUVORK5CYII=

ターミナルで実行してもイマイチなので、ここはサイト上で実行しました。
青い画像が色々と作れる

kazu_kichi_67kazu_kichi_67

Maps

% go run 4-More-types/maps.go                    
{40.68433 -74.39967}

Map literals

% go run 4-More-types/map-literals.go 
map[Bell Labs:{40.68433 -74.39967} Google:{37.42202 -122.08408}]

Map literals continued

% go run 4-More-types/map-literals-continued.go 
map[Bell Labs:{40.68433 -74.39967} Google:{37.42202 -122.08408}]

Mutating Maps

% go run 4-More-types/mutating-maps.go         
The value: 42
The value: 48
The value: 0
The value: 0 Present? false

Exercise: Maps

https://pkg.go.dev/strings#Fields

% go run exercise-maps.go
PASS
 f("I am learning Go!") = 
  map[string]int{"Go!":1, "I":1, "am":1, "learning":1}
PASS
 f("The quick brown fox jumped over the lazy dog.") = 
  map[string]int{"The":1, "brown":1, "dog.":1, "fox":1, "jumped":1, "lazy":1, "over":1, "quick":1, "the":1}
PASS
 f("I ate a donut. Then I ate another donut.") = 
  map[string]int{"I":2, "Then":1, "a":1, "another":1, "ate":2, "donut.":2}
PASS
 f("A man a plan a canal panama.") = 
  map[string]int{"A":1, "a":2, "canal":1, "man":1, "panama.":1, "plan":1}
kazu_kichi_67kazu_kichi_67

Function values

% go run 4-More-types/function-values.go       
13
5
81

Function closures

% go run 4-More-types/function-closures.go 
0 0
1 -2
3 -6
6 -12
10 -20
15 -30
21 -42
28 -56
36 -72
45 -90

んーめっちゃ違和感。

この辺を読んでいたらだいぶ腹落ちしてきた。
https://nowokay.hatenablog.com/entry/20130522/1369202662

ところどころまだ出てきてない概念があるので、後で読み直す。
https://fa-works.com/magazine/article/comparing-golang-with-java/
https://future-architect.github.io/articles/20200311/

Exercise: Fibonacci closure

% go run 4-More-types/exercise/exercise-fibonacci-closure.go
0
1
1
2
3
5
8
13
21
34