Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
2019-13 実践 Go 言語/2019-13 golang
Search
Cybozu
PRO
July 04, 2019
Programming
6
160k
2019-13 実践 Go 言語/2019-13 golang
Cybozu
PRO
July 04, 2019
Tweet
Share
More Decks by Cybozu
See All by Cybozu
生産性向上チームの紹介
cybozuinsideout
PRO
1
870
サイボウズQAの紹介
cybozuinsideout
PRO
1
270
試験仕様書の英語化をやってみたら試験仕様書の本質が見えてきた
cybozuinsideout
PRO
0
270
販売管理オペレーターが開発チームの一員となった話
cybozuinsideout
PRO
0
260
主体的な活動で巨大な影響範囲のテストを乗りこなしていく話
cybozuinsideout
PRO
1
260
Garoon 開発チーム / Garoon development team
cybozuinsideout
PRO
2
2.9k
OSSの脆弱性との向き合い⽅
cybozuinsideout
PRO
2
76
既存プロセスからの脱却と変化に適応するために必要なこと
cybozuinsideout
PRO
2
580
スプリント内で試験を完了させるには?アジャイル・スクラム開発に参加したQAエンジニアの悩みと対策
cybozuinsideout
PRO
1
550
Other Decks in Programming
See All in Programming
SwiftUIで使いやすいToastの作り方 / How to build a Toast system which is easy to use in SwiftUI
lovee
3
150
雑に思考を整理する技術と効能
konifar
60
29k
はてなにおける CSS Modules、及び CSS Modules に足りないもの / CSS Modules in Hatena, and CSS Modules missing parts
mizdra
7
930
二郎系ラーメンのコールで学ぶ AST 解析
memory1994
PRO
7
1.7k
What We Can Learn From OSS
inouehi
0
420
ADRを一年運用してみた/adr_after_a_year
hanhan1978
7
2.4k
コーンフレークから始める モデリング会話入門
ogurotakayuki
0
370
Elm 0.19.0 Changes
bkuhlmann
0
490
Fragment Composition of GraphQL
quramy
7
1k
VS Code をプロダクトにどう取り込むか
onomax
1
360
1BRC--Nerd Sniping the Java Community
gunnarmorling
0
340
#phpcon_odawara オープン・クローズドなテストフィクスチャを求めて / open closed test fixtures
77web
3
230
Featured
See All Featured
Gamification - CAS2011
davidbonilla
76
4.6k
BBQ
matthewcrist
80
8.8k
Keith and Marios Guide to Fast Websites
keithpitt
408
22k
The Brand Is Dead. Long Live the Brand.
mthomps
49
29k
Clear Off the Table
cherdarchuk
84
310k
ParisWeb 2013: Learning to Love: Crash Course in Emotional UX Design
dotmariusz
104
6.6k
Optimising Largest Contentful Paint
csswizardry
8
2.4k
Building Your Own Lightsaber
phodgson
99
5.7k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
6
1.5k
GitHub's CSS Performance
jonrohan
1025
450k
Docker and Python
trallard
34
2.7k
How STYLIGHT went responsive
nonsquared
92
4.8k
Transcript
実践GO言語 2019/07/04 開発本部 深谷敏邦
対象者 ▪ A Tour of Go を読んだ ▪ プロダクションコードは書いたことがない ▪
Go で HTTP client/server を書きたい
アジェンダ ▪ はじめに ▪ 準備 ▪ HTTP Server ▪ HTTP
Client ▪ テスト ▪ json 処理 ▪ エラー処理 ▪ context ▪ go modules ▪ Go 関連のツール
はじめに ▪ はじめに ▪ 準備 ▪ HTTP Server ▪ HTTP
Client ▪ テスト ▪ json 処理 ▪ エラー処理 ▪ context ▪ go modules ▪ Go 関連のツール
はじめに ▪ この講義では簡単なHTTPサーバを例にGoを書く際のエッセンスを学びます ▪ サードパーティライブラリは扱いません ▪ Goは言語機能が少なく、ライブラリよりもイディオムを駆使する言語です – もっと良い書き方、機能がないかと思っても本当にないです –
イディオムを覚えて筋力でプログラムしましょう
準備 ▪ はじめに ▪ 準備 ▪ HTTP Server ▪ HTTP
Client ▪ テスト ▪ json 処理 ▪ エラー処理 ▪ context ▪ go modules ▪ Go 関連のツール
準備 ▪ 講義で使用するコンパイラをダウンロードしてください – go (1.12 くらい)
HTTP Server ▪ はじめに ▪ 準備 ▪ HTTP Server ▪
HTTP Client ▪ テスト ▪ json 処理 ▪ エラー処理 ▪ context ▪ go modules ▪ Go 関連のツール
HTTP Server ▪ Go は HTTP Server に関する機能は標準ライブラリに含んでいる – net/http
▪ 重要な型 – Handler – ResponseWriter – Request – Server
Handler型 ▪ net.httpがユーザーリクエストに反応するためのコールバックインターフェース ▪ ユーザーリクエストはReqeust型に入っている ▪ ReponseWriter型を通してレスポンスする type Handler interface
{ ServeHTTP(ResponseWriter, *Request) }
Request型 ▪ https://golang.org/pkg/net/http/#Request – Method – URL – Header –
Body ▪ この型はClientで使うものと共通 ▪ Bodyがio.ReadCloserインターフェースを満たしているので、ioutil.ReadAllなどで中身 を取り出す ▪ 中身を取り出すのはコードを書く人の責任 ▪ 読んでいる最中にエラーが起きたら、それを処理するのも書く人の責任
ResponseWriter型 ▪ https://golang.org/pkg/net/http/#ResponseWriter – Header().Add()/Header().Set()でヘッダを設定する – WriteHeader でステータスコードを設定する – Writeでレスポンスを返す
▪ この型はio.Write型をみたすのでfmt.Fprintとかが使える ▪ Writeを呼ぶと自動的にWriteHeader(http.StatusOK)がよばれる – エラーステータス返すなら必ずWriteHeaderを先に呼ぶ ▪ エラーを返すならhttp.Errorが便利
ルーティング ▪ リクエストルーティングは簡単なパスベースならhttp.ServeMuxがつかえる – これ自体もHandler ▪ メソッドとか正規表現とか使いたいんですが ▪ 適当なライブラリを探して使う –
決定版はない印象 ▪ 筋力で自前でルーティング – 細かいバリデーションが必要なエンドユーザー相手でなければあり – ルータライブラリが必要になるようなサーバをGoで書きたいですか?
Server型 ▪ https://golang.org/pkg/net/http/#Server ▪ 実際にコネクションを受け付けてHandlerを起動してくれる型 ▪ フィールドはおおよそオプションだが、Timeoutは設定すべき – 後述する Context
を使うとさらに細かいTimeoutが設定可能 ▪ ListenAndServerを呼べばサーバが起動する
HTTP Client ▪ はじめに ▪ 準備 ▪ HTTP Server ▪
HTTP Client ▪ テスト ▪ json 処理 ▪ エラー処理 ▪ context ▪ go modules ▪ Go 関連のツール
HTTP Client ▪ Go は HTTP Client に関する機能は標準ライブラリに含んでいる – net/http
▪ 重要な型 – Client – Request – Response
Client型 ▪ https://golang.org/pkg/net/http/#Client ▪ HTTPリクエストを行うための型 ▪ フィールドはオプションでおおよそ何も指定しなくても良い ▪ http.DefaultClientは使わない方が良い –
設定がグローバル – テストで差し替えれない ▪ 基本的にはDoメソッドだけを使えばよい – Getなどの専用メソッドがあるが、後述するContextが使えない
Request型 ▪ https://golang.org/pkg/net/http/#Request ▪ 見間違いではなくサーバで見たものと同じ ▪ フィールドが多くてびっくりするが、http.NewRequestで生成する
Response型 ▪ https://golang.org/pkg/net/http/#Response ▪ StatusCode にステータスコードが入っている ▪ Body は io.ReadCloser
で ioutil.ReadAll などを使って自分でコンテンツを読む必 要がある ▪ HTTP keep-aliveを利用するにはプログラマが自前でCloseする必要がある – 忘れがちなので注意
テスト ▪ はじめに ▪ 準備 ▪ HTTP Server ▪ HTTP
Client ▪ テスト ▪ json 処理 ▪ エラー処理 ▪ context ▪ go modules ▪ Go 関連のツール
テスト ▪ HTTP関連のテストならhttptest.Serverを使うのがらく – 使い終わったらCloseすること ▪ table driven testが便利
json 処理 ▪ はじめに ▪ 準備 ▪ HTTP Server ▪
HTTP Client ▪ テスト ▪ json 処理 ▪ エラー処理 ▪ context ▪ go modules ▪ Go 関連のツール
JSON処理 ▪ Go は JSONに関する機能は標準ライブラリに含んでいる – encoding/json ▪ 基本型や一部の標準ライブラリに含まれる型を相互変換することができる ▪
自分で定義した型も変換できるがここでは扱わない
Marshal ▪ Goの型からJSONバイト列に変換すること ▪ json.Marshalかjson.Encoderを使う – json.Encoderはio.Writerを使えるのでhttp.ResponseWriterと相性が良い – と思わせておいて、エラーが起きるとWriteHeaderとの順番で難しいことに なるのでjson.Marshalを使うのが良い気がする
Unmarshal ▪ バイト列をGoの型に変換すること ▪ json.Unmarshalかjson.Decoderを使う – json.Decoderがio.Readerを使えるのでhttp.Responseと相性が良い
JSONと型のマッピング ▪ Goのstructはフィールドにタグがかける – どう使うかは言語側は規定していないので好きに使える ▪ jsonパッケージはこの機能を活用する
タグ付け ▪ タグでフィールドにマッピングされるJSONのキーを指定する ▪ マッピングするフィールドは公開する必要がある ▪ 実はタグがなくても公開メンバが自動的にマップされるがわかりにくいのでつ けた方が良い ▪ JSONにキーが現れない場合はそのフィールドは空になる
– キーの存在を判定するならポインタを使うと良い type Foo struct { ID int `json:"id"` Data string `json:"data"` }
エラー処理 ▪ はじめに ▪ 準備 ▪ HTTP Server ▪ HTTP
Client ▪ テスト ▪ json 処理 ▪ エラー処理 ▪ context ▪ go modules ▪ Go 関連のツール
エラー処理 ▪ Goはいわゆる例外を持たない ▪ "エラー"の扱いはコンベンションによる
エラーを返す ▪ エラーを返す関数は戻り値の最後にerror型を書く ▪ 戻り値は次の性質を満たすようにする – もしエラーが起きていないならerror型はnilにする – もしエラーが起きているならerror型はnon-nilである –
もしエラーが起きているならtypeN達は何らかの無効な値である ▪ 大抵ゼロ値が使われる func foo() (int, string, error) { if some error is happened { return 0, "", errors.New("error"); } return 1, "ok", nil }
エラーを判定する ▪ 関数がコンベンションを満たしているなら次のように書ける ▪ エラーを返す関数ではerror型を最初にifでチェック ▪ nilでないなら上位に返す ▪ nilなら処理を継続する func
bar() error { n, s, err := foo() if err != nil { return err } // use n and str return nil }
error型 ▪ 組み込みのインターフェース – error ▪ errors.Newやfmt.Errorfを使って生成する ▪ 特定のエラーであることを伝えたり、付加情報をつけるために自前で定義する 場合もある
プラクティス ▪ Goのerrorはいわゆる例外とは異なりスタックトレースを持たない ▪ そのため雑にerrorを上位に伝播するだけだと何が起こったかわかりにくい – 深いロジックで起こったioエラーがmain関数でログされても意味がない ▪ エラーが起きた時は次のことを行うのが良い –
エラーが起きた箇所でのロギング – エラーをfmt.Errorfなどで付加情報をつけて投げ直す ▪ xerrorsを使うとスタックトレースも手に入る
context ▪ はじめに ▪ 準備 ▪ HTTP Server ▪ HTTP
Client ▪ テスト ▪ json 処理 ▪ エラー処理 ▪ context ▪ go modules ▪ Go 関連のツール
context ▪ 処理を止めるための仕組み – リクエスト単位のkvsとしても使えるがここでは扱わない ▪ 例えば – HTTPリクエストをタイムアウトさせたい –
外部コマンド呼び出しをタイムアウトさせたい – goroutineの実行を途中で止めたい
contextパッケージ ▪ contextは標準のcontextパッケージとコンベンションで実現する ▪ contextを扱う関数は第一引数にcontext型を受け取る – 引数名はctx ▪ context.Doneはchannelで、closeされるとそのcontextが終了したことを示す ▪
context生成関数がCancelFuncを返すなら必ずその関数を呼び出す
HTTPサーバでのContext ▪ HTTPハンドラーのrequest構造体が持つContext()からcontextを取得できる ▪ このcontextはユーザーのコネクションがクローズされると終了する – すなわちcontext.Doneがcloseされる ▪ クライアントのコネクションが閉じた時、ハンドラーの処理を停止できる
HTTPクライアントのContext ▪ http.Clientはcontextのコンベンションを守っていない – contextが後で追加されたため ▪ 引数で直接contextを渡す代わりに、http.Requestに対してcontextを乗せる – WithContext ▪
context.WithTimeoutなどと組み合わせて使う
go modules ▪ はじめに ▪ 準備 ▪ HTTP Server ▪
HTTP Client ▪ テスト ▪ json 処理 ▪ エラー処理 ▪ context ▪ go modules ▪ Go 関連のツール
Go modules ▪ 最近標準で用意されるようになった依存管理方法 – npm, maven, gradle的な ▪ Go
modulesを使うとGOPATHは不要 – GOPATHを使っているとmodulesが誤作動するので注意 ▪ 依存パッケージのバージョンが指定できるのでvendoringが不要になる
使い方 ▪ 初期化 – go.mod が生成される ▪ 依存の追加・削除 – import文から依存がgo.modに追加される
– ベリファイファイルのgo.sumも生成される ▪ ビルド – 自動的に依存がダウンロードされる $ go mod init github.com/foo/bar $ go get github.com/hoge/fuga $ go mod tidy $ go build
Go 関連のツール ▪ はじめに ▪ 準備 ▪ HTTP Server ▪
HTTP Client ▪ テスト ▪ json 処理 ▪ エラー処理 ▪ context ▪ go modules ▪ Go 関連のツール
Go 関連のツール ▪ formatter – go fmt – goimports ▪
不要なimportを消してくれるのでgoimportsを使うのがオススメ ▪ checker/linter – go vet ▪ コーディングミスっぽいものを探してくれる – golint ▪ コードスタイルをチェックしてくれる