プログラミング言語Go 第1章 メモ

# 「チュートリアル」
書籍：[プログラミング言語Go](https://www.amazon.co.jp/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E8%A8%80%E8%AA%9EGo-ADDISON-WESLEY-PROFESSIONAL-COMPUTING-Donovan/dp/4621300253/ref=sr_1_1?ie=UTF8&qid=1551468616&sr=8-1&keywords=%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E8%A8%80%E8%AA%9EGo)
第1章 「チュートリアル」 の要点と思われる箇所を自分のメモ用にまとめました。

## 準備
https://golang.org/dl/
上記からインストーラをダウンロードしてGoを使えるようにする。

https://play.golang.org/
簡単なコードを実行したい場合は上記が便利。


##1.1 ハロー、ワールド
- Goはコンパイル言語で、コンパイルはbuildサブコマンドを使う。

```
 $ go build xxx.go
```
- goコマンドにはサブコマンドがいくつもあり代表例がrun。go runで1つ以上の.goファイルを指定するとコンパイルしたものの実行結果を確認できる。

```
 $ go run xxx.go
```
- GoはUnicodeを扱い、世界中のすべての言語テキストを処理できる。
- Goにはパッケージという概念があり、必要な機能はパッケージをimportして利用する。
- mainパッケージ内のmain関数からプログラムが実行される。(C++のmain関数と同じ。)
- Goはコードの書式に関して強い立場をとっている。**スタイルが厳密**にあり、**gofmtをつかうと標準書式に成型してくれる**。(ので、gofmtを積極的に使おう。)★
   - 基本的に改行は他言語のセミコロン相当に解釈される。
   - 関数の開き括弧 { は関数宣言の終わりと同じ行にないといけない。
   - ...

##1.2 コマンドライン引数
- os.Argsでプログラム実行の引数が把握できる。
- スライスとは、動的に大きさが決まる配列要素のシーケンスのようなもの。
 - 要素には[i]の添え字でアクセスする。添え字の数字は0始まり。 Ex) os.Args[1]
 - 要素数はlen(s)で得られる。 Ex) len(os.Args)
 - スライスに添え字[m:n]を適用すると、m番目からn-1番目の要素を参照するスライスになる。m, nは省略可能で、mは省略すると0が, nは省略すると最後の要素まで指定されたことになる。
- コメントは//で始める。/* */ も使える。
- var宣言で初期化をしないとその型のゼロ値となる。(整数値は0, 文字列は""など。)
- :=は省略変数宣言。初期化の値に基づき適切な型を変数に割り当てる。大域的スコープでは利用できない。
- インクリメント演算子は後置のみ。かつ、**インクリメントを利用した行は文であり、式として利用できない** (j = i++ などとできない)。前置・後置の戻り値の違いを理解していないためにおこるバグが発生しない。
- Goには**値を2つ以上返す関数がある**。値もエラーも返してほしいケースなどで活躍！

```.go
  for i, arg := range os.Args[1:] {
```
- _ はブランク識別子と呼ばれ、変数名が必要だけどその変数を利用しないケースで利用する。 

```.go
  for _, arg := range os.Args[1:]  { // rangeの第一戻り値はindexだが、indexを利用しない場合 _ を使う。
```
- 以下は同じ変数宣言。初期値が重要であれば1番目の表現を、初期値が問題でないなら2番目の表現を使うのが良い。

```.go
  s := ""
  var s string
  var s = ""
  var s string = ""
```

##1.3 重複した行を見つける
- mapのkeyには==で比較できる値が入る。valueは何でもOK。
- valueがないindexに添え字でアクセスするとvalueがゼロ値で評価される。
- **mapの繰り返しの順序は規定されておらず、むしろ実際には実行時にランダム**に異なる。暗黙のバグが防げる。
- fmt.Printfはverbと呼ぶ変換を持つ(Cのprintfみたいに%dとか%sを使う。)。慣習的にfで終わるフォーマット関数はフォーマット規則を利用する。
- goにはnilという概念があり、nilはエラーなしを意味することがある。
- 関数とほかのパッケージレベルのエンティティはどのような順序で宣言してもOK。関数呼び出しが、その関数定義の前にあってもよい。
- mapが関数へ渡される場合、その関数はmapの参照のコピーを受け取る。(呼び出し元と呼び出され側は同じmapを扱う。関数内でmapを操作したら、呼び出し元のmapもその操作が反映される。)

##1.4 GIFアニメーション
-  importしたパッケージはコード中では最後の要素の名前でそのパッケージを参照する。
  -  Ex) image/gif をimportした場合、gif.GIF{… 
- constの値は、数値、文字列、ブーリアンでなければならない。
- {}を使うとコンポジットリテラルとしてコンポジット型のインスタンスを生成できる。

```.go
  []color.Color{color.White, color.Black}
  Anim := gif.GIF{LoopCount:nframes}
```

- 大域的な場所で省略変数宣言する( := を使う)と以下のエラーになる。var宣言して=して対応。

```
syntax error: non-declaration statement outside function body
```

##1.5 URLからの取得
- Goはインターネットを通した情報の送受信や低レベルネットワーク通信のためにnetパッケージが存在。
- os.Exit(1) はプロセスをステータスコード1で終了させる。

##1.6 URLからの並行な取得
- ゴルーチンは関数の並行した実行。チャネルはゴルーチンが特定の型の値を他のゴルーチンへ渡すことを可能にする通信機構。
- 1つのゴルーチンがチャネルに対して送信または受信を試みると、そのゴルーチンは他のゴルーチンが対応する受信操作あるいは送信操作を試みるまで待たされ、値が転送された時点で2つのゴルーチンは処理を先に進める。

##1.7 ウェブサーバ
- Goライブラリを使えばウェブサーバを容易に作成できる。
- サーバサイドの実装ではURLにハンドラ関数を結びつける。

```.go
  http.HandleFunc("/", handler) // handlerはハンドラ関数。ハンドラ関数にhttpリクエストの処理を記述する。
```

- **ハンドラはリクエストごとに別のゴルーチンで実行**され、複数のリクエストを同時に処理できる。それぞれが並列処理になるので**スレッドセーフにする必要がある**
- Goでは関数リテラルが使える関数リテラルは使われる時点で定義される無名関数。以下のHandleFuncの第二引数が関数リテラル。

```.go
  http.HandleFunc("/", func(w, http.ResponseWriter, r *http.Request) {
      lissajous(w)
  })
```

##1.8 残りの項目
- **switch文はcaseが次のcaseに通り抜けることはない** (fallthrough文を利用するとこの動作は無効になる。)。この言語仕様により case内での break 忘れのバグが起きにくくなる。
- switch文はオペランドを指定しなくても記述できる。以下が例。

```.go
  switch {
  case x > 0:
      return 1
  ....
```

- goto文も使えるが、自動生成コード以外での利用は推奨されない。コードが読みにくくなるから。
- Goではポインタを扱え、&で変数のポインタに、*でポインタの値を参照できる。ポインタへの演算はない。
- go docコマンドでドキュメンテーションを参照できる。

```
  $ go doc http.ListenAndServe
```

## 練習問題解答例
https://github.com/tsuyuzaki/go/tree/master/GoProgrammingLanguage/chapter01