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
AIツール開発ワークショップ(Dify)【サイボウズ新人研修2025】
cybozuinsideout
PRO
15
17k
モバイル【サイボウズ新人研修2025】
cybozuinsideout
PRO
3
3.4k
Git/GitHub を使う上で知っておくと嬉しいかも Tips【サイボウズ新人研修2025】
cybozuinsideout
PRO
11
9.2k
GitHub Copilot活用【サイボウズ新人研修2025】
cybozuinsideout
PRO
14
13k
ソフトウェアライセンス【サイボウズ新人研修2025】
cybozuinsideout
PRO
12
7.8k
エンジニアのためのアウトプット講座 〜知識をシェアするはじめの一歩〜【サイボウズ新人研修2025】
cybozuinsideout
PRO
7
4.3k
Docker入門【サイボウズ新人研修2025】
cybozuinsideout
PRO
12
10k
セキュリティ【サイボウズ新人研修2025】
cybozuinsideout
PRO
2
3.1k
TLS 1.3をざっと理解する【サイボウズ新人研修2025】
cybozuinsideout
PRO
2
1.9k
Other Decks in Programming
See All in Programming
MCP連携で加速するAI駆動開発/mcp integration accelerates ai-driven-development
bpstudy
0
250
AIのメモリー
watany
12
1.2k
GitHub Copilotの全体像と活用のヒント AI駆動開発の最初の一歩
74th
5
1.5k
MCPで実現できる、Webサービス利用体験について
syumai
7
2.3k
React 使いじゃなくても知っておきたい教養としての React
oukayuka
18
5.2k
[SRE NEXT] 複雑なシステムにおけるUser Journey SLOの導入
yakenji
1
910
ソフトウェア設計とAI技術の活用
masuda220
PRO
25
7.3k
LLMは麻雀を知らなすぎるから俺が教育してやる
po3rin
3
1.9k
AI Ramen Fight
yusukebe
0
120
Flutterと Vibe Coding で個人開発!
hyshu
1
220
TypeScriptでDXを上げろ! Hono編
yusukebe
4
930
リバースエンジニアリング新時代へ! GhidraとClaude DesktopをMCPで繋ぐ/findy202507
tkmru
7
1.7k
Featured
See All Featured
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
Stop Working from a Prison Cell
hatefulcrawdad
271
21k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
30
2.2k
GraphQLとの向き合い方2022年版
quramy
49
14k
Mobile First: as difficult as doing things right
swwweet
223
9.9k
[RailsConf 2023] Rails as a piece of cake
palkan
56
5.7k
Designing Experiences People Love
moore
142
24k
Being A Developer After 40
akosma
90
590k
Done Done
chrislema
185
16k
Six Lessons from altMBA
skipperchong
28
3.9k
How STYLIGHT went responsive
nonsquared
100
5.7k
Facilitating Awesome Meetings
lara
54
6.5k
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 ▪ コードスタイルをチェックしてくれる