Go Conference 2014 autumn に参加してきた
GoCon2014秋にいってきたよ! とりあえず、まとめと見つけられた分のスライド載せました。
先にまとめ
- 朝から全開で実用的な話が多く、ためになる話多かった。
- Goの哲学をRob Pike先生本人から聞けるなんてなかなか無いですよね。
- 8時間ハードだった
- ケツ痛い
- 英語力磨かねば。。。
- スタッフの皆さん、発表者のみなさま、会場+協賛をしてくださった楽天さん、Klabさん。素晴らしいイベントを有難うございました!
Keynote
- Rob Pike
Goはなぜ成功したか
- シンプルさ、こそが本質
- 他の様々な言語は、複雑すぎる
各言語は、他の言語のいいところを吸収しあうことで大きくなり、複雑化して発展してきた
Goはそれをしない
Go1の時点で言語機能は固定化された。
- 色々な機能を追加してほしい、という声がある、が、それは追加しない。
もちろん、いくつかの機能は必要
- 正しい機能を実装する!
可読性
プログラミングにおいて非常に重要
言語が難しいことによって、様々なやり方が生まれてしまい、あとで何故コレが動くのかわからなくなる。
言語がシンプルなら、書き方は絞られる。
可読性は信頼性
表現力が高いからといって、可読性が高いとは限らない。
- 実装コストが高くなったり、パフォーマンスも予測しづらくなる。
正しい言語機能
- 機能のための機能ではない
- 目的を正しく認識し、必要な機能を
Goの目的
- サーバソフトウェアを強力に作るためのもの
各要素がそれぞれ単純に組み合わさっている
Gopherってシンプルだよね!(笑
単純さ
- Goは実際には複雑だけど、シンプルにする仕組みがある
- GC
- goroutines
- constant
- interface
- package
GC
- 複雑さを隠す最たるもの
- コレのお陰で、コードがシンプルに書ける
- メモリの管理や、データのやり取りの厄介なことを隠蔽してくれる
並列性
プログラムを独立実行しているようにかける
- goroutine
- channel
- select
goroutine
定数
- ただの数!!
- 無限の精度整数型
- 無限の浮動小数点型
- etc...
- 完璧にできてるわけではないが、かなり普通の数字のようになってる
- こうすうるのはややこしかったけど、その代わりGoはシンプルになった
interface
- メソッドの集合体
- 想像以上に複雑
型アサーションと型switchは本来の予定にはなかった
Goの最も特徴的な機能
- io.Reader / io.Writerなどは、パイプのように扱えて、複雑さを隠蔽した
package
- ライブラリ構成の設計
- これの設計には非常に時間がかかった
まとめ
- 単純さは設計が難しい
- コレのために戦う価値がある
Goに入ってはGoに従え
- うかいさん
- Goの可読性について
Go Readability Approver
- Go言語のReadabilityをレビューするチーム
- より良いGo言語の書き方を教える
- メインのプロジェクトではないコードを見る
Readabilityスキルとは
Goのコード
- 明瞭・簡潔
- 使いやすいAPI
- 適切なコメント
- 素直なコードフロー
- goroutineなどのお陰で、コードの流れが読みやすくなる。
- コードの実装を読むのに、Goの実装を読むのが一番理解しやすい。
優れたツール
- ツールによるサポートを常に適用するカルチャー
- go fmt
- go vet
- golint
- godoc
ツールだけでは十分ではない
- 読みやすいコード == 情報が認識しやすい/脳に負担がかからない
- Goはシンプル
Readability Reviews
- ミス・バグチェック
- 見やすくレイアウトされているか
- コードフローはわかりやすいか
APIはわかりやすいか
気になってきた点を紹介
ミス/バグ
errorチェック
- regex.Compileのerrorチェックを飛ばす人がいる
regex.MustCompileでエラーチェック
- やっていいのは、初期化の時(varかinit())のみ
deferを使ったcloseのチェック
- close自体もエラーチェックする
値自体で
-1がエラー
みたいな判定をさせるのではなく、値とエラーを分ける。- error毎のデータを定義して、それを判定する
errorの設計
-
- 値と型が共にnilの場合
- 間違えやすいので注意
interface実装の型チェックには、structにinterfaceを実装するのではなく。。。
_ scan.Write =
などのようにすることで、型チェックだけできる
見やすく
- structフィールドのレイアアウト
- 関連が深いものをブロックに分ける
- 長い行
- 長さ制限はないので、1行に
- なので、名前は簡潔に
- 与えられたコンテキストのなかで、わかり易い名前にする
- 長い名前がわかりやすいわけじゃない
- 冗長な名前をさける
- レシーバ変数は数文字で良い
素直なコードフロー
基本のコードパスのインデントは最小に
- errorの分岐もシンプルに
- funcを分割したり
- if else並べるぐらいならswitch
time.Duration
- constは型を持たないので、time.Durationにする型変換は不要
chanを使えば、sync.Mutex, sync.Condが不要な時がある
型がわかっているようなときにreflectを使わない
テストコード
- わかりやすいテストメセージ
- 独自アサート関数を定義するより、言語の機能を使う
- コメントにAPIの使い方を書くくらいなら、Exampleテスト
コメント
- packageコメントを書く
- mainパッケージは、コマンドのコメント
- Exportしている名前にはコメントつける
- 対象の名前を先頭に
コメントがわかりにくかったり書きにくい場合は、API設計を考えなおした方がいい
APIデザイン
- 適切な名前のpackageを作る
- APIをシンプルにする
- 返り値は複数使えるので、出力変数としてポインタを使わない
- Cとかでよくある
- 非同期APIより同期API
- chanをpackageを超えて使わない
- 非同期化は使う側がgoroutine + chanで制御
読みやすいコードを書くには
- 明瞭に表現すること
質問
- 名前付き戻り値について、いつ使うか
- コメントで補足しないとわからなくなるような場合(string, string, intなどのようになって、1つめ2つなんだっけ?としまう場合)
- deferの中で、返り値を弄りたい場合などは、名前がついていないとそもそもいじれない
Gardner & Go
- Tシャツ作ったよ
- とあるゲームの色を。。。w
- FreeGuhoでEC販売してるよ
- 1500 + 160だよ
- Golang Tシャツもあるよ
- 2500 + 160
App Engine for Golang Preformance
- 普段はApp EngineでJava書いてる
App Engine for Go
- 最初の呼び出し部分はmain()じゃない
- init() -> http.HandleFunc("/", handler)とかしていく
App Engine for Goの微妙な所
- Version upが遅い
- GOMAXPROCS = 1限定
- Goが本気出せない
Managed VMとは
- Google Compute Engine上でApp Engineのコンテナを動かす事ができる
- dockerで動いてる
GOMAXPROCSも挙げたりできる
- 本気出せる
微妙な点
- deployが遅い
- autoscaleの最小値が1
- 常時課金発生
Performance
Golang@ISUCON
なんでGo?
- 改善効率の高さ
取り組んだこと
- プロセスキャッシュ
- タスク分散処理
プロセスキャッシュ
- データをプロセス上に全て保持しておく
永続化は適度なタイミングでRedisに保存したりする
グローバルに変数置いて。。。とかやると、Goroutine複数作ると整合性の保証が必要になる
Race Condition
syncパッケージ
- 各種ロックを使う
- sync.RWMutek
- sync/atmic
atomic.Value
- golang 1.4
- プロセス上にatomicにデータ更新できるストア
- シンプルにかける
タスクの分散処理
- 画像・動画などは重複処理したくない
Task Queueing
- goroutineとchannelでそのまま使える
- goroutineの本数で調整できる
重複処理
処理先を振り分ける
- consistent hashライブラリ
- stathat/consistent
mackerel-agent徹底解説
Mackerel
- サーバ監視・管理ツール
- エージェントがGo
mackerel-agentとは
- 1分毎にAPIにメトリクスをPOSTするエージェント
なぜGo?
- マルチプラットフォーム対応
- シングルバイナリ
- フットプリントが小さい
プラグインもGo
- sensu互換の出力
ソースコード解説
- 外部への依存: tomlを利用
windowsで動かなくなるオチを防ぐため、シグナルハンドルではos.Interruptを使う
chan chan
- チャンネルでチャンネルを渡す
- 複雑なので、シグナルハンドルもメイン処理に入れたほうがいいんじゃないか?というのはある
loopの状態管理
- enumっぽくtype作って処理
なんか色々改善点あればご指摘ください
Why my Go program is slow?
- methaneさん
- CPUプロファイラの話
runtime/pprof
- サンプリングプロファイラ
- モンテカルロ法に似てるやり方だよ
- 計測方法として、実行時のサンプルを大量にとって、重い箇所を特定する
net/http/pprofなんかがHTTPではおすすめ
解析するプログラムもpprofという名前
- google preftools
- Go 1.4からはGo版になってる
- ぐっと便利になってるので、ここだけでも1.4にするといいよ
デモ
- webで展開できたり、アセンブリ単位で見れたりしてすごい
どこが重いか
- GC
- memory copy
- function call
GC
- GOGC=400とかすると、急激な負荷に唐突に突っ込むとGC頑張っちゃって負荷が高くなってしまうので、それを遅くする
memory copy
- 文字列便利だからってコピーしまくると大変
- []byteとか使おう
function call
- 引数がレジスタじゃなくてスタック渡し
Golang JP Community
- 日本のGolang JPのコミュニティの紹介
Go at Gengo
- Gengoの中の人
- 中でめっちゃ使ってる
the early days
GoShip
- Goベースのデプロイメントツール
- なぜGoを使った?
- productionに入れる前に、試しに作ってみるのに調度良かった
Go API
どこから入れるべきか
- まず、クリティカルじゃない所から入れよう
- 全てを一度にrewriteしようとしないほうがいいよ
Dive in
Managing dependencies
- まず試したのはここら
- go get
- gom
- godep
- 結局シンプルなshellscriptになった
- godepが標準ぽいけど。
- まず試したのはここら
Test Fixtures
reflect
をつかって頑張ってる- Gorpの`Insertable`を使うと簡単にできる
- LoadFisturesみたいなの定義して使ってる
- ただ、fixtureテストが並列化できないよね
- go test -p 1してる。。
Quick Wins
- graceful shutdownの例
- gofmt -s / gofmt -w は走らせよう
- go test -race / go importsしよう
- go vet 大事
One Year Down
- 抱えてる問題
- logging
- slow build times
- test fixtures
NSQ-Centric Archtecture
- Greg
- Gunosyの人
chatサーバをGoで
- Go + webview + websocket
NSQ
- message queue
- SPOFなしでスケーラブル
プッシュ型のメッセージ通知
- データフォーマットはなんでも良い
問題点
- メッセージが1回以上とどく
- 順序保証がない
NSQのアーキテクチャの話
自作したChatアプリのアーキテクチャの話
面白そうだけど。。。話が飛んじゃって流れがわかんなくなった。。。
Hacking Go Compiler Internals
- moriyoshi
対象の人
- Go に拡張いれたいなー、コンパイラーどうなってんのかなーって人
Lexer
Parser
- Lexerが作ったTokenを抽象構文木(AST)に変換する
yaccで作られてるよ
Braket operator overloadの例
- typecheck 型推論の部分
- walk
print()関数はdebugの時に便利だよ
- printfっぽいやつ
Roll-up
- 一見大変そうだけど、中身は凄くシンプルでhackしやすいよ!
nginx-build
- bokkoさん
- mercariのひと
本題
Go製のnginxビルドツール
nginxのビルドするのがつかれたので、作った
nginxのビルドは、現実的にはいろいろなものをダウンロードしてきたりしないといけない
- configure optionsを大量に追加しないといけない
しかもそのビルドスクリプトをメンテしないといけない
これらまとめて解決してくれる
使い方
- binary を持ってきて、mkdir work -> nginx-build -d work みたいにする
- 3rd partyモジュールを、iniファイルに指定しておくと、まとめてダウンロードしてくれる
なんでGoで?
Terraformで始めるGo言語
- @tkak
- 楽天の人
楽天のInfrastracture as Code
- サービスいっぱい = サーバの種類が多い
- 最下部のインフラ層に向いてそうなterraformがリリースされたので使ってみた
Terraform
- オーケストレーションツール
- Go製
- 様々なクラウドサービスをコードで管理
TerraformとGo
- Terraform Plugin開発
v2.0からフレームワーク機能をサポート
やりやすいから、このへんから始めてみては。
Goでビルドパイプラインツールを書いた話
ainoyaさん
walter
- CIでのビルドパイプラインを実現する
なんでGo?
- ジョブの実行をgoroutineで
- データの受け渡しをするのにchannel
- このへんが扱いやすそうだったので
その他Tips
プロジェクト構成について
- coreos/etcd を参考にした
- テスト、ビルドはshell
package管理
- submoduleでやってたけど辛かった
- Godep
ログ出力
- どこも軒並み自前で用意してた
- golang/glogを利用
Goの所感
- Object指向的な書き方をしてしまって、ぎこちない感じになった
- channelをつかってみた、厳しくなったらsync.Mutex
go/parser go/astの話
- http://yuroyoro.net/gocon_2014_autumn_lt/#/
yuroyoroさん
GoのASTをビジュアライズするツールを作った
- ASTって何が嬉しいっけ
- 静的解析
- Altjs
- golint
- GopherJS
I/Oに依存したテスト
I/Oに依存したテストをどうするか
- RubyだとStringIO
- Goでは、bytes.Buffer がある
bytes.Buffer
- []byteにいろいろメソッドが生えた感じ
io.ReadWriter
テストコードの実践
ポイント
- I/O依存部分を切り出す
インターフェースに依存して書く
ここまでー
Destributed system
- marioさん
- 分散システムの話
Consul
- 実装の例の話