【Go】Tour of Go に沿って所感を書きながら勉強する
前回の導入編がこちらです。
さあ、How to Write Go Codeをやってみるぞ!
- How to Write Go Code
- A Tour of Go
- time
- go run
- Packages
- Imports
- Exported names
- Functions
- Functions continued
- Multiple results
- Named return values
- Variables, Variables with initializers
- Short variable declarations
- Basic types
- Zero values
- Type conversions
- Type inference
- Constants
- Numeric Constants
- For
- For continued
- For is Go's "while"
- Forever
- 参考文献
How to Write Go Code
見てきたけど、パッケージの作り方についてやライブラリの取得方法を学べるみたいだね!
今は、よくわからなそうだから見るのをやめるぞ!
A Tour of Go
先にこっちのA Tour of Go をすることにする。
日本語ページもあるみたいだ。
time
// source: https://go-tour-jp.appspot.com/welcome/4 package main import ( "fmt" "time" ) func main() { fmt.Println("Welcome to the playground!") fmt.Println("The time is", time.Now()) }
このソースを見ると以下の3つが主に予約語なのかな。
- package
- import
- func
それぞれなんとなくイメージはつくね。
fmtはフォーマットのIOを制御しているらしく、Println
のところに%v
とか書けるみたい。よくあるやつだ。
timeは時間の計測と表示機能を提供しているらしいね。これもよくあるやつだ。理解できる。
time.goというファイルを作って実行しみるとエラーが出た。
/go-playground ❯ go build # _/Users/usermei/go-playground ./time.go:8:6: main redeclared in this block previous declaration at ./hello.go:5:6
これはmain()がhello.goのとダブるからbuildできなかったのかな?
time.goを消してtime.goの中身をhello.goに移植してやってみる。
/go-playground ❯ ./go-playground Welcome to the playground! The time is 2019-04-23 01:47:41.387461 +0900 JST m=+0.001004734
やった!動いた!
けどね、試すごとにフォルダ作る必要がありそうだ。
helloとかtimeとかちょっと手間だなぁ。
go run
buildしないで実行できるコマンドgo run
がありました!
こでれ、go run hello.go
みたいにファイル別で実行できるようになりました。
これ以降はrunで試していきたい。
/go-playground ❯ go run hello.go hello, world /go-playground ❯ go run time.go Welcome to the playground! The time is 2019-04-23 02:14:03.485511 +0900 JST m=+0.000271016
Packages
Goはパッケージで管理されており、最初はmainパッケージを見るんだね。
// source: https://go-tour-jp.appspot.com/basics/1 package main import ( "fmt" "math/rand" ) func main() { fmt.Println("My favorite number is", rand.Intn(10)) }
"math/rand"
はmathパッケージの中のrandパッケージという2段回掘り下げたものみたいだね。
rand.Intn(10)
はrandパッケージのIntn関数を呼んでいるのかな。
擬似乱数を生成できるみたいですね。
じゃあ実行しみてるぞ!
/go-playground
❯ go run packages.go
My favorite number is 1
でた!
繰り返しても同じものが出てきたので擬似乱数となっていることが分かる(にわか)。
Imports
importは(
, )
で囲む書き方をfactoredインポートステートメント( factored import statement )と呼ぶみたい。
もう一つ書き方があってimport "fmt"
というよくある書き方ですね。
Go言語的にはfactoredインポートステートメントを進めているみたいです。
まとまりができて見やすくなるから?
// ok import ( "fmt" "math" ) // ng? import "fmt" import "math"
Exported names
GO言語では、exportする名前(exported name)は頭文字が大文字だとイメージ的にpublicで小文字から始まる文字がイメージ的にprivateのようです。分かりやすいような気がする。
// publicだから参照できる fmt.Println(math.Pi) // privateだから参照できない fmt.Println(math.pi)
Functions
Go言語の関数は名前を書いた後ろに型名を書くらしいです。Javaとは違います。TypeScriptとは似ていますね。
func add(x int, y int) int { return x + y } func main() { add(42, 13) }
なんで後ろに型を指定する書き方を実装したのかはこのページにあるみたいです。訳してQiitaに投稿している方がいらっしゅいました。ありがたや。
C言語のmain()をGo風に書いた場合を見ると、左から右にかけて読むことができるらしいです。
// source: https://blog.golang.org/gos-declaration-syntax func main(argc int, argv *[]byte) int
Functions continued
2つ以上の引数が同じ型なら一つにまとめて書くことができるらしいですね。
どっちの書き方がいいのでしょうか?ググっても分からなかった。
func foo(x int, y int) int ↓ func foo(x, y int) int
Multiple results
関数の戻り値を複数にできるようですね。タプルというやつか。
これは同じ型が2つ以上並んでいても省略はできないみたいです。エラーが出ます。
// source: https://go-tour-jp.appspot.com/basics/6 package main import "fmt" func swap(x, y string) (string, string) { return y, x } func main() { a, b := swap("hello", "world") fmt.Println(a, b) }
Named return values
戻り値に名前をつけることができるらしいですね。JavaScriptでObjectのプロパティを指定し戻り値とするみたいものかと思ったらちょっと違う。戻り値で指定した変数を普通に関数内で使えるみたい。初めて見たぞ。関数のドキュメントとして定義しておくみたい。分かりやすいって良いよね!
そして、returnでは何も返さないとすることでokなんだ。この名前付き戻り値で何も返さないreturnのことを"naked" returnというらしい。これは短い関数の時に使って、長い関数の時は見づらいのでやめるべきらしい。
// source: https://go-tour-jp.appspot.com/basics/7 package main import "fmt" func split(sum int) (x, y int) { x = sum * 4 / 9 y = sum - x return } func main() { fmt.Println(split(17)) }
Variables, Variables with initializers
var
で変数定義らしい。同じ型なら省略できるみたい。
省略した場合の代入方法もあるんだね。
var hensu, hen, su: int var foo, bar int = 2, 4 // これもok var hoge, fuga = 1, true // これはng var hoge, fuga = 1
Short variable declarations
関数内ならvar
を省略できるらしいね。関数外でもできると思ってた。
func somefunc() { k := "syoryaku" }
関数外に書いて怒られてみた。
syntax error: non-declaration statement outside function body
Basic types
bool string int
こういうのを
基本型(組み込み型)
というらしい。
他にもたくさんあるみたい。特にrune
というのは初見。
int32 の別名 Unicode のコードポイントを表す
Unicode のコードポイントを表したい時に便利なんだね。使い機会はあるか知らないけど。
int32ってことは4バイトでUnicodeを表すのか。一文字4バイト使う未来。
rune
Zero values
初期値与えないと、勝手に
ゼロ値( zero value )
というのが入るみたい。JavaScriptみたいにundefined
みたいにはならないんだね。しかも、コンパイルではエラーにならないんだ。ぬるぽが減りそう。それに、書く手間が減りそう。
Type conversions
変数 v 、型 T があった場合、 T(v) は、変数 v を T 型へ変換します。
日本語難しい。型変換らしい。Go言語の型変換は全部明示的に書くらしい。エラー減りそう。
// source: https://go-tour-jp.appspot.com/basics/13 i := 42 f := float64(i) u := uint(f)
Type inference
型の推論ができるらしい。i := 42
みたいな。これを使うとレビュアーも推論できる。果たしてどっちの推論が早いかな?
Constants
定数ってやつだ。これを待っていた。基本的にvar
よりもconst
を使うからありがたい。
文字(character)、文字列(string)、boolean、数値(numeric)のみで使えます。
らしい。const somefunc = () => 'teisu'
みたいなJavaScriptのようにはできないんだね。
定数は := を使って宣言できません。
ok。だけど、:=
を使って宣言できるようになるのはconst
の方がよかったのでは?知らんけど。
var
の方が使い道多いのかな。
一文字目は大文字にするみたい。関数の外部でconst
を使ったら半ば強制的にパブリック?
試しに小文字にしてもエラーにならなかった。
Numeric Constants
大きいあたいも表現できるらしい。needInt(大きい数)
を使ってとっても大きい値を表現できるみたい。小さい値はneedFloat
みたいだね。
const ( // 1を100ビット左シフト、つまり10進数でいくつかわからんほど大きい Big = 1 << 100 // Bigを99ビット右シフト、つまり10進数で2. Small = Big >> 99 )
For
ついにきたぞforだ。()
がない。
for i := 0; i < 10; i++ { }
初期化ステートメント: 最初のイテレーション(繰り返し)の前に初期化が実行されます 条件式: イテレーション毎に評価されます 後処理ステートメント: イテレーション毎の最後に実行されます
へー。初期化ステートメントっていくつもかけるのかな?
for i := 0, j := 0; i < 10; i++ { j++ }
syntax error: unexpected :=, expecting {
だめなのか。,
で区切るのが間違いなのかな。
ggって探したら微妙に違った。
for i, j := 0, 1; i < 10; i++ { fmt.Println(j) }
1 1 1 1 1 1 1 1 1 1
できた。
For continued
初期化ステートメント、後処理ステートメントは書かなくても動くらしい。
whileみたいだね。
for ; sum < 1000; { }
For is Go's "while"
こっちがGo言語のwhileらしい。
for sum < 1000 { }
Forever
無限ループらしい。これは遊びでは使わないようにしましょう。日本の一部だと補導されたり、起訴されたりします。
for {}
参考文献
- A Tour of Go,入手先 https://go-tour-jp.appspot.com/welcome/1
- For loop of two variables in Go - Stack Overflow, 入手先 https://stackoverflow.com/questions/38081807/for-loop-of-two-variables-in-go