最近ちょっとGoを触った感想とか振り返りとか1

仕事で使いそうだったので勉強してみた感想とか。振り返りとか。

# 学習履歴

- [Tour of go](https://tour.golang.org/list) をやって Go を完全に理解する。
- いろいろ作った。
  -  [aws-cost-notification](https://github.com/takat0-h0rikosh1/aws-cost-notification)
  - [go-clean-architecture-sample](https://github.com/takat0-h0rikosh1/go-clean-architecture-sample)
  - [grpc-with-go](https://github.com/takat0-h0rikosh1/grpc-with-go)
- [みんなの Go 言語](https://www.amazon.co.jp/%E6%94%B9%E8%A8%822%E7%89%88-%E3%81%BF%E3%82%93%E3%81%AA%E3%81%AEGo%E8%A8%80%E8%AA%9E-%E6%9D%BE%E6%9C%A8-%E9%9B%85%E5%B9%B8/dp/4297107279)を読む。
- [Effective Go](https://golang.org/doc/effective_go.html) を読んでさらに理解を深める。← いまここ

# 触ってみて

## コンパイルが早い

Scala を書いてるときのいわゆる **待ち** みたいなのを感じなくなったかも（コンパイルとかユニットテストとか）。Mac も大きな声で泣き叫んで発熱することもなくなった感。

## 組み込みのAPIが充実

用意されているものが優秀なので、簡易なHTTPサーバーを作るのにフレームワークなどを使う必要はなさげ（個人差ありそう）。

## 実行環境を選ばない

`go build` で生成したバイナリはランタイムに依存しないので配布しやすい。コンテナを作るときはマルチステージビルドでバイナリだけ入れとくとか巷で良く見かける。

```dockerfile

FROM golang:1.13-buster as builder

RUN mkdir /app
WORKDIR /app

COPY src ./src
RUN go build -o /main ./src/cmd/*.go

FROM debian:stretch-slim

COPY --from=builder /main .

ENTRYPOINT ["./main"]
```

軽量のコンテナは、CA証明書が入ってなかったりするから Image に固めるアプリケーションが HTTP Client 実装してたりしたときは注意。

# 構文に関して

## 迷いのなきエラーハンドリング

変数に入れて nil かどうかを愚直に評価していく。とにかくこれな印象。

```go
if err := file.Chmod(0664); err != nil {
    log.Print(err)
    return err
}
```

いわゆるガード節を書いていくので else とかは書かないほうが良い。

```go
f, err := os.Open(name)
if err != nil {
    return err
}
d, err := f.Stat()
if err != nil {
    f.Close()
    return err
}
codeUsing(f, d)
```

たまにはモナドが恋しいときもある。

## 命名でパッケージ外からの可視性が決まる

先頭文字を大文字にすることで他パッケージからの参照が可能となる。
小文字だと参照不可。最初これ知らなくてハマった。

```go:t_horikoshi.go
package model

type T_horikoshi struct {
	Name string
}

type t_horikoshi struct {
	name string
}
```

```go:main.go
package main

func Ref() {
	t := domain.T_horikoshi{Name:"t_horikoshi"}
	//t := domain.t_horikoshi{name:"unexported..."}
	fmt.Print(t)
}
```

## リソースのクローズとかやってくれる Defer が便利


リソースのクローズ処理のため Defer という仕組みが用意されている。
関数内に宣言しておくと最後まで処理を行った後に自動的に実行してくれるのでので便利。

```go
type ExchangeRate struct {
	Quotes []Quote
}

type Quote struct {
	High             string
	Open             string
	Bid              string
	CurrencyPairCode string
	Ask              string
	Low              string
}

func GetExchangeRatePerYen() (rate *ExchangeRate, err error) {
	resp, err := http.Get("https://www.gaitameonline.com/rateaj/getrate")
	if err != nil {
		return nil, err
	}

	defer func() {
		if err := resp.Body.Close(); err != nil {
			log.Fatal("close resources", err)
		}
	}()

	bytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	rate = new(ExchangeRate)
	if err := json.Unmarshal(bytes, rate); err != nil {
		return nil, err
	}
	return rate, nil
}
```

`resp.Body.Close()` が `error` を返すので無名関数で実装しなければならない。

## interface を実装する

Scala脳に染まってたので extends どうやるんやとか思ってたら、interface に定義したメソッドを実装したらその時点で継承が完了するみたい。

<strike>世間でダックタイピングと呼ばれているもの。<strike>

↑これわたし勉強不足だったのですが、Structural typing と呼ばれるもので構造の宣言や定義によって型の互換性や透過性を保証し、型チェックを行わない Duck typing とは全くもって対をなすというものでした。

https://golang.org/doc/faq#implements_interface

@c-yan さんコメントありがとうございます。

```go:main.go
package main

import "fmt"


type Human interface {
	Call() string
}

func VoiceChecker(h Human) {
	fmt.Print(h.Call())
}

type Animal struct {}

func (a Animal) Call() string {
	return "bau!bau!"
}

type Insect struct {}

func (i Insect) Call() string {
	return "paru!paru!"
}

func main() {
	VoiceChecker(Animal{})
	VoiceChecker(Insect{})
}
```

# つづく...

そのうちに書きます。