Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.

メルカリ・ソウゾウでは どうGoを活用しているのか?

7.694 Aufrufe

Veröffentlicht am

会津大のGo勉強会で使用した資料です。

Veröffentlicht in: Technologie
  • You can ask here for a help. They helped me a lot an i`m highly satisfied with quality of work done. I can promise you 100% un-plagiarized text and good experts there. Use with pleasure! ⇒ www.WritePaper.info ⇐
       Antworten 
    Sind Sie sicher, dass Sie …  Ja  Nein
    Ihre Nachricht erscheint hier
  • Writing good research paper is quite easy and very difficult simultaneously. It depends on the individual skill set also. You can get help from research paper writing. Check out, please ⇒ www.HelpWriting.net ⇐
       Antworten 
    Sind Sie sicher, dass Sie …  Ja  Nein
    Ihre Nachricht erscheint hier
  • Hi there! I just wanted to share a list of sites that helped me a lot during my studies: .................................................................................................................................... www.EssayWrite.best - Write an essay .................................................................................................................................... www.LitReview.xyz - Summary of books .................................................................................................................................... www.Coursework.best - Online coursework .................................................................................................................................... www.Dissertations.me - proquest dissertations .................................................................................................................................... www.ReMovie.club - Movies reviews .................................................................................................................................... www.WebSlides.vip - Best powerpoint presentations .................................................................................................................................... www.WritePaper.info - Write a research paper .................................................................................................................................... www.EddyHelp.com - Homework help online .................................................................................................................................... www.MyResumeHelp.net - Professional resume writing service .................................................................................................................................. www.HelpWriting.net - Help with writing any papers ......................................................................................................................................... Save so as not to lose
       Antworten 
    Sind Sie sicher, dass Sie …  Ja  Nein
    Ihre Nachricht erscheint hier
  • Dating direct: ❤❤❤ http://bit.ly/39pMlLF ❤❤❤
       Antworten 
    Sind Sie sicher, dass Sie …  Ja  Nein
    Ihre Nachricht erscheint hier
  • Sex in your area is here: ❶❶❶ http://bit.ly/39pMlLF ❶❶❶
       Antworten 
    Sind Sie sicher, dass Sie …  Ja  Nein
    Ihre Nachricht erscheint hier

メルカリ・ソウゾウでは どうGoを活用しているのか?

  1. 1. メルカリ・ソウゾウでは どうGoを活用しているのか? The Go gopher was designed by Renee French. The gopher stickers was made by Takuya Ueda. Licensed under the Creative Commons 3.0 Attributions license. 1 2017/07/22(土) @会津大Go勉強会
  2. 2. 自己紹介 メルカリ/ソウゾウ 上田拓也 twitter: @tenntenn ■ コミュニティ活動 Google Cloud Platform User Group (GCPUG) Tokyo Goビギナーズ golang.tokyo Go Conference ■ 業務 GAE/Goでメルカリカウルを作ってます GoやGCPコミュニティを盛り上げる仕事 Gopherを描く仕事(LINEスタンプ) 2
  3. 3. ソウゾウ エキスパートチーム 技術をアウトプットするところに技術は集まる ■ エキスパートチームとは? ● 50%以上の時間を技術コミュニケーションへの貢献に充てる ■ エキスパートチームの役割 ● 社内に新しい技術を取り取り込む ● 社外のコミュニティなどを通じて社会へ還元する ■ エキスパートチームの活動 ● カンファレンス・勉強会の開催/運営 ● 対外的な講演活動 ● 執筆、雑誌への寄稿、インタビュー ● 社内外での担当技術の普及推進 3 @tenntenn 担当:Go・GCP @mhidaka 担当:Android メンバー
  4. 4. デブサミ(夏)に登壇します 4 【A-3】 コミュニティ活動と企業の相互作用 ~コミュニティへの貢献と組織活動への還元~
  5. 5. 「エキスパートGo」を開催しました 5 http://tech.mercari.com/entry/2017/07/13/103000 ※ この資料は「エキスパートGo」の資料を元にしています
  6. 6. アジェンダ ● Goを知る ○ Goの特徴 ○ Goのドキュメントとコミュニティ ● メルカリ・ソウゾウにおけるGoの活用事例 ○ Gaurun ○ go-httpdoc ○ メルカリ アッテ ○ メルカリ カウル ○ バナーツール ● Goの開発ノウハウ ○ インタフェースと抽象化 ○ Goとテスト ○ エラー処理 6
  7. 7. Goを知る 7
  8. 8. Goとは? 8 Googleが開発しているプログラミング言語 ■ 特徴 ● シングルバイナリ・クロスコンパイル ● 強力でシンプルな言語設計と文法 ● 並行プログラミング ● 豊富な標準ライブラリ群 ● 周辺ツールの充実
  9. 9. Goの特徴 − シングルバイナリ・クロスコンパイル − ■ 環境変数のGOOSとGOARCHを指定する 開発環境とは違うOSやアーキテクチャ向けに クロスコンパイルできる 9 シングルバイナリになるので 動作環境を用意しなくてよい # Windows(32ビット)向けにコンパイル $ GOOS=windows GOARCH=386 go build # Linux(64ビット)向けにコンパイル $ GOOS=linux GOARCH=amd64 go build ※ go build はGoのソースコードをビルドするコマンド
  10. 10. Goの特徴 − 強力でシンプルな言語設計と文法 − ■ スクリプト言語の書きやすさ ● 冗長な記述は必要ない ■ 型のある言語の厳密さ ● 曖昧な記述はできない ■ 考えられたシンプルさ ● 機能を増やすことで言語を拡張していくこと はしない 10 Goに入ってはGoに従え = 言語の思想を理解しよう
  11. 11. Goの特徴 − 並行プログラミング − ■ ゴールーチン ● 軽量なスレッドに近いもの ● goキーワードをつけて関数呼び出し ■ チャネル ● ゴールーチン間のデータのやり取り ● 安全にデータをやり取りできる 11 チャネル ゴールーチン A ゴールーチン B データ データ // 関数fを別のゴールーチンで呼び出す go f()
  12. 12. Goの特徴 − 豊富な標準ライブラリ − ■ 標準ライブラリ一覧  https://golang.org/pkg/ 12 net/http HTTPサーバなど archive, compress zipやgzipなど crypto 暗号化 encoding JSON, XML, CSVなど html/template HTMLテンプレート os, path/filepath ファイル操作など
  13. 13. Goの特徴 − 周辺ツールの充実 − ■ go tool として標準/準標準で提供 ■ サードパーティ製のツールも充実 ■ IDEによらない独立したツールとして提供 13 go build ビルドを行うコマンド go test xxxx_test.goに書かれたテスト コードの実行 go doc, godoc ドキュメント生成 gofmt, goimports コードフォーマッター golint コードチェッカー、リンター gocode コード補完
  14. 14. ドキュメントを読む 14 ■ 言語仕様 ● コンパクトな言語仕様なので簡単に読める ■ Go Code Review Comments (日本語訳) ● Goらしい書き方が学べる ■ Effective Go ● Code Review Commentsより詳しい内容 ■ パッケージドキュメント ● ドキュメントをしっかり読む ※できるかぎり本家を参考にすること ※golang.jpは情報が古いので注意
  15. 15. コミュニティに参加する ■ Goビギナーズ ● https://go-beginners.connpass.com/ ● 初心者向けのGoのコミュニティ ■ golang.tokyo ● https://golangtokyo.connpass.com/ ● Goの採用企業間で情報共有をするコミュニティ ■ Go Conference ● https://gocon.connpass.com/ ● 日本最大のGoのカンファレンス ■ Gophers Slack ● https://invite.slack.golangbridge.org/ ● 世界中のGopher(Goのユーザ)が集まる 15
  16. 16. ソウゾウにおけるGoの学習について 16 https://codeiq.jp/magazine/2017/05/50248/
  17. 17. メルカリ・ソウゾウにおける Goの活用事例 17
  18. 18. メルカリ・ソウゾウでのGoの活用事例 18 https://codeiq.jp/magazine/2017/04/50250/
  19. 19. Gaurun 19 ■ 大規模プッシュ配信基盤 ● https://github.com/mercari/gaurun 参考:ハイパフォーマンスGaurun〜メルカリの大規模プッシュ配信を支えるミドルウェア〜
  20. 20. go-httpdoc 20 ■ テストからAPIドキュメントを生成する ● https://github.com/mercari/go-httpdoc ● HTTPハンドラのテストから生成 ● リクエストやレスポンスが記載される ● gRPCやJSON RPCなAPIでも利用可能
  21. 21. メルカリ アッテ ■ 地域コミュニティアプリ ● https://www.mercariatte.com ● 近所の人とモノを取引したり ● コミュニティを通じて同じ趣味の仲間を見つけたり ● GAE/Goで開発 21
  22. 22. メルカリ カウル ■ 本・CD・DVD専用フリマアプリ ● https://mercarikauru.com/ ● バーコードスキャンでかんたん出品 ● 同じ製品の値段比較ができ最安値が分かる ● GAE/Goで開発 22
  23. 23. バナーツール ■ バナーの入稿を管理するツール ● 式で配信条件を設定 ● 1ソースで複数の環境に対応 23
  24. 24. バナーツール ■ バナーの入稿を管理するツール ● 式で配信条件を設定 ● 1ソースで複数の環境に対応 24 バナーツール ・配信条件 ・レスポンス バナー取得 OS, APIバージョン などの変数 条件に当てはまるバナー 画像URL, 遷移先URL アプリ
  25. 25. デモ 25 YouTubeで見る
  26. 26. 配信条件式の評価 ■ バナーの配信条件に条件式を用いる ● Goの式としてパースできる独自形式 ● 型定義を式で表現できるようにしてある 26 バナー取得 GET /banner/?os=1 String(os) == "1" バナー画像URL 配信条件: バナーツール
  27. 27. 条件式からUIの自動生成 ■UIを自動生成し簡単に入力できるにする ● 条件式からJSON Schemaを生成する ● JSON EditorでJSON SchemaからWeb UIを生成 27 os: iOS ▼ Android UIを生成する部分 リクエストから もらう部分 ※一部簡略化している 生成したWeb UI String(os) == Enum(__os, "0,1", "iOS,Android") String(os) == "1" UIで入力した値を式へ展開
  28. 28. Goの開発環境 28
  29. 29. エディタは何を使っているのか? 29 ■ とくに決まったものはない
  30. 30. Gogland ■ JetBrains製のGoのIDE ● https://www.jetbrains.com/go/ ● ソウゾウのメンバーの多くが使っている ● 補完が高速 ● インタフェース実装へのジャンプ ● リファクタリング機能 ● デバッガ 30
  31. 31. 詳しくはMercari Tech Blogで 31 http://tech.mercari.com/entry/2017/03/23/124437
  32. 32. コードの書式を揃える ■ gofmt ● 読み方:ごーふむと ● 標準のフォーマッタ ● 絶対に使う ● -s オプションで冗長な書き方をシンプルにできる ■ goimports ● import文を追加/削除してくれる ● 未使用パッケージのimportはエラーなので必須 ● フォーマットもかける ● -s オプションがない 32
  33. 33. コードの品質を保つ ■ go vet ● バグである可能性の高いものを検出する ■ golint ● コーディングスタイルをチェックする ■ errcheck ● エラー処理が適切に行われているかチェックする ■ その他のツール ● http://haya14busa.com/ci-for-go-in-end-of-2016/ 33
  34. 34. デバッグ ■ GDB ● https://golang.org/doc/gdb ● 有名な古き良きデバッガ ● Go自体にカスタマイズされてるわけではない ■ Delve ● https://github.com/derekparker/delve ● Go専用のデバッガ ● ゴルーチンやチャネルにも対応 ■ panicデバッグ ● panicを使ってデバッグ ● スタックトレースが出るので便利 34
  35. 35. リファクタリング ■ gomvpkg ● https://golang.org/x/tools/cmd/gomvpkg ● パッケージ名の変更ができるツール ■ gorename ● https://golang.org/x/tools/cmd/gorename ● 識別子の名前を変更するツール ■ eg ● https://golang.org/x/tools/cmd/eg ● exampleベースのリファクタリングツール ● 参考:https://rakyll.org/eg/ 35
  36. 36. インタフェースと抽象化 36
  37. 37. 型・メソッド・インタフェース 37 ■ Goの抽象化はインタフェースで行う ● 抽象化の概念はインタフェースしかない ● インタフェースを正しく理解する必要 ● 型とメソッドと深い関係がある
  38. 38. 組み込み型 ■ 組み込み型 ● int,int8,int16,int32,int64 ● uint,uint8,uint16,uint32,uint64 ● uintptr,byte,rune ● float32,float64 ● complex64,complex128 ● string ● bool ● error 38
  39. 39. // 組み込み型を基にする type Int int // 他のパッケージの型を基にする type MyWriter io.Writer // 型リテラルに基にする type Person struct { Name string } typeを使った型の作成 type <型名> <型リテラル>|<型名> 39 intとIntは別の型として扱われる
  40. 40. typeで新しく型が作れるもの ■ 組み込み型 int, float64, string など ■ 型リテラル 構造体、インタフェース、 マップ、スライス、チャネル、関数 など ■ 名前付きの型 パッケージの内外で作った型 40 別の型として再定義できる
  41. 41. 型エイリアス(Go 1.9以上) ■ 41 ■ 型のエイリアスを定義できる ● 完全に同じ型 ● キャスト不要 ● エイリアスの方ではメソッド定義はできない type Applicant = http.Client ■ %Tは同じ元の型名を出す type Applicant = http.Client func main() { fmt.Printf("%T", Applicant{}) } http.Client
  42. 42. type Hex int func (h Hex) String() string { return fmt.Sprintf("%x", int(h)) } メソッドとレシーバ type で定義した型はメソッドのレシーバにできる 42 Playgroundで動かす // 100をHex型として代入 var hex Hex = 100 // Stringメソッドを呼び出す fmt.Println(hex.String())
  43. 43. レシーバにできる型 ■ typeで定義した型 ● ユーザ定義の型をレシーバにできる ■ パッケージ内の型 ● パッケージ内であれば定義ファイルは別でもOK ■ ポインタ型 ● レシーバに変更を与えたい場合 ■ 参照型 ● マップやスライスなどもレシーバにできる 43
  44. 44. レシーバにできない型 ■ 組み込み型 ● 組み込み型にはメソッドはない ● 設けたい場合はtypeで再定義すれば良い ■ パッケージ外の型 ● 型定義とメソッド定義を別パッケージにできない ● パッケージ外の型はtypeで再定義すれば良い ● 埋め込みを使うこともできる ■ インタフェース型 ● レシーバにできるのは具象型のみ 44
  45. 45. 関数をレシーバにする ■ 関数型を基に型を定義してレシーバにする 45 type Func func() string func (f Func) String() string { return f() } Playgroundで動かす
  46. 46. レシーバとnilの関係 ■ 値がnilの場合でもメソッドは呼べる 46 type Hoge struct{} func (h *Hoge) Do() { fmt.Println(h) } func main() { var h *Hoge h.Do() h = &Hoge{} h.Do() } Playgroundで動かす 参考:Understanding nil by Francesc Campoy(動画/スライド)
  47. 47. インタフェース ● メソッドのリストを持つ ● メソッドのリストがインタフェースで規定しているものと一致 する型はインタフェースを実装していることになる 47 var s interface { String() string } // インタフェースを実装していることになる s = Hex(100) fmt.Println(s.String()) Playgroundで動かす type Hex int func (h Hex) String() string { return fmt.Sprintf("%x", int(h)) }
  48. 48. interface{} ■ empty interface ● メソッドリストが空なインタフェース ● つまりどの型の値も実装していることになる ● JavaのObject型のような使い方ができる 48 var v interface{} v = 100 v = "hoge" Playgroundで動かす
  49. 49. 関数にインタフェースを実装させる ■ 関数にメソッドを持たせる 49 type Func func() string func (f Func) String() string { return f() } func main() { var s fmt.Stringer = Func(func() string { return "hi" }) fmt.Println(s) } Playgroundで動かす
  50. 50. 構造体の埋め込み ■ 構造体に匿名フィールドを埋め込む機能 50 type Hoge struct { N int } // Fuga型にHoge型を埋め込む type Fuga struct { Hoge // 名前のないフィールドになる }
  51. 51. 埋め込みとフィールド ■ 埋め込んだ値に移譲(継承とは違う) 51 type Hoge struct {N int} type Fuga struct {Hoge} f := Fuga{Hoge{N:100}} // Hoge型のフィールドにアクセスできる fmt.Println(f.N) // 型名を指定してアクセスできる fmt.Println(f.Hoge.N) Playgroundで動かす
  52. 52. 埋め込みの特徴 ■ 型リテラルでなければ埋め込められる ● typeで定義したものや組み込み型 ● インタフェースも埋め込められる ■ インタフェースの実装 埋め込んだ値のメソッドもカウント 52 // Stringerを実装 type Hex int func (h Hex) String() string { return fmt.Sprintf("%x", int(h)) } // Hex2もStringerを実装 type Hex2 struct {Hex} Playgroundで動かす type Stringer interface { String() string }
  53. 53. インタフェースと埋め込み ■ 既存のインタフェースの振る舞いを変える 53 type Hoge interface{M();N()} type fuga struct {Hoge} func (f fuga) M() { fmt.Println("Hi") f.Hoge.M() // 元のメソッドを呼ぶ } func HiHoge(h Hoge) Hoge { return fuga{h} // 構造体作る } Mの振る舞いを変える 参考:インタフェースの実装パターン
  54. 54. インタフェースの設計 ■ メソッドリストは小さく ● 共通点を抜き出して抽象化しない ● 一塊の振る舞いを一つのインタフェースにする ● トップダウンではなくボトムアップに設計する ■ 型階層はつくれない ● Goでは型階層は作れない ● 抽象化はすべてインタフェース ● 型階層ではなくコンポジットで表現する 54
  55. 55. io.Readerとio.Writer ■ ioパッケージは良いお手本 ● 1メソッドしか無いので実装しやすい ● 入出力をうまく抽象化している ○ ファイル、ネットワーク、メモリ etc… ● パイプのように簡単に入出力を繋げられる 55 type Reader interface { Read(p []byte) (n int, err error) } type Writer interface { Write(p []byte) (n int, err error) }
  56. 56. インタフェースを組み合わせる ■ 複雑なインタフェースは埋め込みを使う ● インタフェースでも埋め込みを使うことはできる ● 振る舞いが複数ある場合は埋め込みで組み合わせる 56 type ReadWriteCloser interface { Reader Writer Closer }
  57. 57. 抽象化とリフレクション ■ ジェネリクスの代わりにリフレクション? ● リフレクションはパフォーマンスに影響を与える ● リフレクションは使う箇所をちゃんと選ぶ ● encodingパッケージでは利用されれている ■ インタフェースで代用する ● 型スイッチで代用できる事が多い ● タイプするのが面倒なら自動生成しよう ○ go generateを使う ● 静的解析も選択肢のうちの一つ 57 参考:https://www.slideshare.net/takuyaueda967/2016-go#101
  58. 58. Goとテスト 58
  59. 59. go test ■ 単体テストを行うためコマンド  _test.goというサフィックスの付いた  ファイルを対象にしてテストを実行 59 # mypkgのテスト行う $ go test mypkg ok mypkg 0.007s # 失敗する場合 $ go test mypkg --- FAIL: TestHex_String (0.00s) hex_test.go:11: expect="a" actual="A" FAIL FAIL mypkg 0.008s hex.go ⇒ hex_test.go
  60. 60. go testのオプション(一部) ■ -v ● 詳細を表示する ■ -cpu ● 実行する並列度を指定する ● 複数のコアを使ったテストができる ■ -race ● データの競合が起きないかテストする ■ -cover ● カバレッジを取得する
  61. 61. testingパッケージ ■ testを行うため機能を提供するパッケージ  *testing.T型のメソッド使う。 type Hex int func (h Hex) String() string { return fmt.Sprintf("%x", int(h)) } 61 package mypkg_test import "testing" func TestHex_String(t *testing.T) { expect := "a" actual := mypkg.Hex(10).String() if actual != expect { t.Errorf(`expect="%s" actual="%s"`, expect, actual) } }
  62. 62. testingパッケージでできること ■ 失敗理由を出力してテストを失敗させる Error, Errorf, Fatal, Fatalf ■ テストの並列実行 Parallel go testの-parallelオプションで並列数を指定 ■ ベンチマーク  *testing.B型を使う ■ ブラックボックステスト testing/quickパッケージ
  63. 63. テスティングフレームを使わない理由 ■ アサーションはない 自動でエラーメッセージを作るのではなく、 ひとつずつErrorfを使って自前で作る ■ テストはGoで書く テストのための新しいミニ言語を作らない ■ 比較演算子だけはツライのでは? google/go-cmpを使うと良い   参考:https://golang.org/doc/faq#assertions
  64. 64. Exampleテスト ■ テストされたサンプル ● Exampleで始まる関数を書く ● Go Docにサンプルとして出る ● // Output: を書くとテストになる func ExampleHex_String() { fmt.Println(mypkg.Hex(10)) // Output: a } 64
  65. 65. テーブル駆動テスト ■ テスト対象のデータを羅列してテストする 65 参考:https://github.com/golang/go/wiki/TableDrivenTests var flagtests = []struct { in string out string }{ {"%a", "[%a]"}, {"%-a", "[%-a]"}, {"%+a", "[%+a]"}, {"%#a", "[%#a]"}, {"% a", "[% a]"}, } func TestFlagParser(t *testing.T) { var flagprinter flagPrinter for _, tt := range flagtests { s := Sprintf(tt.in, &flagprinter) if s != tt.out { t.Errorf("Sprintf(%q, &flagprinter) => %q, want %q", tt.in, s, tt.out) } } }
  66. 66. ■ テストカバレッジの分析 $ go test -coverprofile=profile fmt $ head profile mode: set fmt/format.go:30.13,31.29 1 1 fmt/format.go:31.29,34.3 2 1 fmt/format.go:67.28,69.2 1 1 fmt/format.go:71.33,74.2 2 1 fmt/format.go:77.85,80.11 3 1 fmt/format.go:84.2,85.11 2 1 fmt/format.go:96.2,96.8 1 1 fmt/format.go:80.11,83.3 2 0 fmt/format.go:85.11,86.21 1 1 coverprofile パッケージ名 テストできるのは パッケージごと 66
  67. 67. カバレッジの可視化 参考:https://blog.golang.org/cover $ go tool cover -html=profile
  68. 68. 差分テスト ■ 増えていくテスト ● プロジェクト規模と共にテストも増える ● 1/3くらいがテスト ● テスト待ちでマージできない ■ 更新してない部分はテストしたくない ● そんなに更新した箇所は多くない ● gitでバージョン管理しているのに... うまく差分だけ テストできないの?
  69. 69. coverprofileの中身 ■ テストが依存しているファイルが分かる mode: set fmt/format.go:30.13,31.29 1 1 fmt/format.go:31.29,34.3 2 1 fmt/format.go:67.28,69.2 1 1 fmt/format.go:71.33,74.2 2 1 fmt/format.go:77.85,80.11 3 1 ... fmt/scan.go:1181.46,1183.4 1 1 fmt/scan.go:1185.29,1187.9 2 1 fmt/scan.go:1195.27,1197.3 1 1 69 テストで通った箇所
  70. 70. coverprofileで差分テストをする ■ coverprofileの生成 ● すべてのパッケージのcoverprofileを生成する ● coverprofileはコミットしておく ■ テストが必要なパッケージを割り出す ● git diff --name-onlyでファイル一覧を取る ● coverprofile内にファイル名が出てるか? ● 出てたらそのパッケージはテスト対象 ■ 差分テスト ● テスト対象のパッケージのみテスト ● テストの際にcoverprofileを生成 ● coverprofileはコミットしておく 参考:http://qiita.com/tenntenn/items/caafa121b90fc7a53a8a
  71. 71. テストとインタフェース ■ テスタブルなコード ● 外部とつながるような部分はインタフェースにする ○ ネットワーク、ファイル、DBアクセスなど ● モックを作ってテストする ○ Go Mockを使う ■ http://qiita.com/tenntenn/items/24fc34ec0c31f6474e6d ○ インタフェースの埋め込みを使う ■ 必要な部分だけ実装する 71 参考:Golangにおけるinterfaceをつかったテスト技法
  72. 72. 環境変数を使う ■ 環境変数を使って切り替える ● os.Getenvで取得できる ● CIでテストを走らせるときに便利 ● DBの接続先など環境に依存する値を保存する ■ github.com/jinzhu/configorを使う 72 var Config = struct { DB string `env:"DB"` }{} func main() { configor.Load(&Config, "config.yml") fmt.Printf("config: %#v", Config) }
  73. 73. エラー処理 73
  74. 74. errorインタフェース ■ error型はインタフェース 74 type error interface { Error() string }
  75. 75. エラーハンドリングをまとめる ■ bufio.Scannerの実装が参考になる ● 途中でエラーが発生したらそれ以降の処理を飛ばす ● すべての処理が終わったらまとめてエラーを処理 ● それ以降の処理を実行する必要ない場合に使う ● エラーハンドリングが1箇所になる 75 s := bufio.NewScanner(r) for s.Scan() { fmt.Println(s.Text()) } if err := s.Err(); err != nil { log.Fatail(err) } 参考:http://jxck.hatenablog.com/entry/golang-error-handling-lesson-by-rob-pike
  76. 76. エラーをまとめる ■ github.com/hashicorp/go-multierrorを使う ● 成功したものは成功させたい ● 失敗したものだけエラーとして報告したい ● N番目の処理は失敗、M番目は成功のように 76 var result error if err := step1(); err != nil { result = multierror.Append(result, err) } if err := step2(); err != nil { result = multierror.Append(result, err) } return result
  77. 77. エラーに文脈を持たせる ■ github.com/pkg/errorsを使う ● File Not Foundとかでは分かりづらい ● 何をしようとした時にエラーが起きたか知りたい ● どんなパラメータだったのか知りたい ● errors.Wrapを使うとエラーをラップできる ● errors.Causeを使うと元のエラーが取得できる 77 if err := f(s); err != nil { return errors.Wrapf(err, “f() with %s”, s) }
  78. 78. 振る舞いでエラーをハンドリングする ■ エラーハンドリングは具象型に依存させない ● エラーの種類で処理を分けたい場合がある ● インタフェースを使い振る舞いでハンドリングする 78 参考:http://deeeet.com/writing/2016/04/25/go-pkg-errors/ func IsTemporary(err error) bool { te, ok := err.(interface { Temporary() bool }) return ok && te.Temporary() }
  79. 79. まとめ ● Goを知る ○ Goの特徴 ○ Goのドキュメントとコミュニティ ● メルカリ・ソウゾウにおけるGoの活用事例 ○ Gaurun ○ go-httpdoc ○ メルカリ アッテ ○ メルカリ カウル ○ バナーツール ● Goの開発ノウハウ ○ インタフェースと抽象化 ○ Goとテスト ○ エラー処理 79
  80. 80. 質疑応答 80
  81. 81. Thank you! twitter: @tenntenn Qiita: tenntenn connpass: tenntenn 81

×