宿題レビュー
func Perm ランダムに添字を作ってくれる
擬似乱数 rand.Seed は毎回やるのは無駄になる
パッケージ変数は短くしない。1文字にするのはブロックスコープの変数。
エラーはos.Stderrへ
並行処理
ゴールーチンとConcurrency
- スレッドみたいなやつ。実際にはスレッドの上でゴールーチンが動く
- プログラムが起動すると、最初にmainゴールーチンが動く
- ゴールーチンリーク ゴールーチンが永遠に動き続ける。
- サーバーで動かしていると起こりがち。
チャネル
|
|
time.Sleep は実際は良くない。危ない。
-
競合を防ぐ方法
- チャネル
- ロックを取る(syncパッケージ)
-
バッファ
- チャネルにバッファを指定しないと初期値は0
- 送受信時の処理のブロック
- チャネルにおけるデータのやり取りを保証できる
-
チャネルの変数は関数をまたいで共有しても競合は起きない。
-
select
- Channel が複数の場合に使用
- Select, case, default
- default は意外と使用すr。
- select と default だけのパターン。チャネルの値をチラ見したいケースなど。
- select にcaseを書かないとブロックし続ける。
- Case: nil
- 何もしない。
- 処理を休む時などに使用。
- 何もしない。
- default は意外と使用すr。
-
ファーストクラスオブジェクト
- Chan の chan
- コールバックでたまに使う
- 何かあった時はこのチャネルを使ってくださいね、という時
- コールバックでたまに使う
<-time.After(5 * time.Minute)- 受信専用のチャネルを返す。
- よくわからん人は自分でtime.Afterを作ってみる。time.Sleepを使えばできる。
- 双方向 or 単方向
- Chan の chan
-
Concurrency の実現
syncパッケージ
-
ロック、sync/atomicによるアトミックな演算
-
sync.Mutex
- Lockメソッドを呼んだ際に、Unlockされるまでにブロックを担保してくれう
-
読み込みが多い場合、Mutexは無駄になってしまう
- RWMutex を使用する
-
WaitGroup
- 複数のゴールーチンを待ち合わせる
- Addした回数と同じ数だけDoneするまでブロックする
- 複数のゴールーチンを待ち合わせる
-
errgroup
- エラーが発生した時にエラーチャネルを返すのが手間。それを防ぐ。
-
sync.Once
-
goroutineがどういった関数から実行されるはわからない。なので、一回しか実行されないように、限定する
-
Panic に注意、下はいけない。recoverは一つのgorounine内でのみ
-
1 2 3 4 5 6 7 8 9func main() { defer func() { recover }() go func() { panic("guha") } select{} }
-
-
チャネルのClose
- 基本的には送信側が閉じる。放っておいても基本的に良い。明示的に閉じたい時たい時だけとじろ
- 二度閉じることは不可。
- 閉じられたチャネルには送信できない。panicが起きてしまう。なので送信側のみCLoseを行う。
- リーク防止のためにCloseを利用する。一つCloseすれば、全てのチャネルに伝わる。
- コンテキストでCloseは使われることが多い。
-
コンテキスト
- ゴールーチンに文脈を持たせる
- コンテキストという名前のものが沢山あるが、context.contextが一番使う
- Go1.6を境に、contextが準標準から標準に移行。
- withcancel キャンセルできるコンテキストとして初期化する
- Background ルートを作る
- cancel を呼ぶと子供のゴールーチンにもキャンセルが伝播するので便利。
- つまり、Context.Doneを使うことで、リークを防止できる。
- 一定の時間が経ったらキャンセルすることを担保してくれるのが withTimeout.
- 外にリクエストを投げる時、時間でタイムアウトを持たせたい時に便利。
- WithValue
- goroutineの間で値を共有できる。
- 例 キャッシュを無視できるように、値を持たせてやる
- エンプティstruct{}
- 容量を消費しないので、引数になどに使った場合、送ったことだけを伝えることができる。
- goroutineの間で値を共有できる。
- コンテキストは引数で回すことが多い
- ラップされるので、値が変わる可能性があるため、フィールドに保存しない
- ゲッターとセッターを両方作る
- ラップされるので、値が変わる可能性があるため、フィールドに保存しない
- 便利なグローバル関数としてはいけない。限られたデータのみ保存
-
rangeはチャネルにも使える。値をとるまで回し続ける。
HTTPサーバとクライアント
-
Handlerの登録は一箇所でやったほうが見通しが良い
-
http.ListenAndServe(":8080", nil)としてnil を指定すると、DefaultServeMux が当たる。その中でルーティングしている感じ。- gollira Mux RESTのルーティングに便利。メソッド GET POST の切り替えが良い感じ
-
net.JoiHotPort(host, port)host + ":" portとはしない。JoinHOstPortではIPv6の時の挙動もよろしくやってくれるので。
-
構造体のタグ… JSON化する時
- フィールドのアノテーション
- 言語仕様上、書き方の記法は決まっていないが、デファクトあり
- go のフィールド名とJSONのフィールド名を別にすることも可能
-
テンプレート
- html と textの2種類がある
- 実際はテンプレートは使わない….
- テンプレートエンジン自体は、テキストテンプレートの場合は使う
- コマンドラインツールの出力の形式を変えたい場合などに使う
- テンプレートエンジン自体は、テキストテンプレートの場合は使う
-
ミドルウェア
- ハンドラより前に行う共通処理
- コンテキストに値を詰め込む
- アクセスログを出す
- 認証処理 など
- ライブラリもあるが、そんなに手間なくスクラッチで作れる
- Net/httpのパッケージという訳ではない。一から作ろう
- ハンドラより前に行う共通処理
-
インターセプター
- ミドルウェアと同じような感じ
-
net/http/httptest
- ハンドラのためのテストを提供
- ハンドラは戻り値を返さない。ライターに書き込む。なので、ライターにhttptest.NewRecoder()を当ててやり、結果を見る。
-
Client
- DefaultClient を直接書くことはしない。
自分用のクライアントをちゃんと作っておいたほうがよい。
- DefaultClient を直接書くことはしない。
-
http.CLient.Do
- 名前がシンプルで良いのはGoの文化
-
http.Transport
- 実際はhttp.ClientではなくTransportが重要な役割を担っている。
- 実際にHTTP通信を行うところ
- http.DefaultTransport
- http.RoundTripper
- http通信をやらずにGRPCをやる時などに、この辺りを弄っていたりすることがある。
- リクエストの前の前処理、後処理、モックサーバーを作りたい場合などに使う。
- テストの時だけ url を差し替えたい時などに便利
##DB
- 実際はhttp.ClientではなくTransportが重要な役割を担っている。
-
ドライバはサードパーティ
-
sql.Open 引数の値は、DBによって異なる
-
Exec, Query, QueryRow
-
Rows.Next() 次のidをforで回して順に持ってくる
-
Rows.Scan でフィールドに落とし込む
トランザクション
- Begin(), BeginTx()
ORM
-
中でリフレクションを使うため、実行時に重たくなる
-
Xo/xoはコンパイルの前に実行するので、一回やっておけば重くない
- mercari の yo も同じ
-
スパナに関してはSQLDBパッケージを使えない GOogleが使ったライブラリがあるので、それを使用する
宿題
- おみくじテスト
- 正月のモック
- ハンドラのテスト 現在時刻のごまかし
LT
connpassから申し込むこと