Upgrade to Pro — share decks privately, control downloads, hide ads and more …

GopherCon 2019 Report

GopherCon 2019 Report

mercari.go #10で発表したGopherCon 2019 Reportの発表資料です.

2709e9b504d8fbaf78ad53866a926e68?s=128

Yu SERIZAWA

August 20, 2019
Tweet

Transcript

  1. GopherCon 2019 Report mercari.go #10 @upamune

  2. About Me @upamune (うぱみゅん) Merpay, Inc. / CodePayment Team Backend

    Engineer
  3. 発表するトーク

  4. How I Write HTTP Web Services After Eight Years Mat

    Ryer 出典: https://medium.com/@matryer
  5. Who is Mat Ryer?

  6. Mat Ryer Blog medium.com/@matryer Podcast Go Time Books Go ⾔語による

    Web アプリケーション開発 Go Programming Blueprints OSS BitBar Testify Gopherize.me etc...
  7. 出典: GoTime https://cdn.changelog.com/uploads/covers/go-time-medium.png Go⾔語によるWebアプリケーション開発 https://www.amazon.co.jp/dp/4873117526 Go Programming Blueprints https://www.amazon.co.jp/dp/B01GQCQ8OW

  8. トーク概要

  9. トーク概要 Go で HTTP service をどう書いているか HTTP service を書く時に重要な要素を紹介 いくつかのパターンを紹介

  10. 重要な要素

  11. 重要な要素 Maintainability Glaceability Code should be boring Self Similar code

  12. Maintainability 最初から Maintainability を考慮して書く 考慮しないと、メンテナンスコストがツールを作る時よりも⼤きくなる可能性

  13. Glaceability 視認性 コードを読んでどれくらい早くコードを理解できるか コードだけではなく、プロジェクト構造なども含まれる 関数、名前空間、変数名、コードの構造、etc...

  14. Code should be boring 他の⼈が理解できるように書く 経験のほとんどない⼈がコードを利⽤する可能性があることを理解するのが重要

  15. Self Similar code コードベース内の他のコードに似たコードがあると、 他の⼈がコードに親しみやすくなる

  16. Design Patterns/Decisions

  17. 全部紹介しきれないのでいくつかピックアップ

  18. Creating a server struct & a constructor for the server

    type server struct { db *someDatabase router *someRouter email EmailSender } func newServer() *server { s := &server{} s.routes() return s } グローバル変数は利⽤しない それを避けるために server 構造体が持つ newServer では依存をセットアップしない テストのため 多くなければ引数でとっても良い ルーティングだけセットアップする
  19. Routing // routes.go func (s *server) routes() { s.router.Get("/api/", s.handleAPI())

    s.router.Get("/about", s.handleAbout()) s.router.Get("/", s.handleIndex()) } ⼀箇所でルーティングを管理する 視認性 ⤴ URL からどのハンドラーを利⽤しているか容易に特定できる
  20. Dealing with data // Respond helper func (s *server) respond(w

    http.ResponseWriter, r *http.Request, data interface{}, status int) { w.WriteHeader(status) if data != nil { err := json.NewEncoder(w).Encode(data) // TODO: handle error } } // Decoding helper func (s *server) decode(w http.ResponseWriter, r *http.Request, v interface{}) error { return json.NewDecoder(r.Body).Decode(v) } 抽象化する 後から Accept ヘッダーや Content-Type ヘッダーに対応することが容易に ヘルパーは http.ResponseWriter と *http.Request を引数で受け取る
  21. Request and response func (s *server) handleGreet() http.HanlderFunc { type

    request struct { Name string `json:"name"` } type response struct { Greeting string `json:"greeting"` } return func(w http.ResponseWriter, r *http.Request) { // do something... } } Handler に関連する Request/Response が⾒つけやすい 関数の中で定義しているので request , response という短い構造体名にできる
  22. Request and response func TestGreet(t *testing.T) { is := is.New(t)

    p := struct{ Name string `json:"name"` }{ Name: "Yu SERIZAWA", } // ... test code } テストの際は request 構造体を参照できないので、リクエストの struct を定義する Name フィールドだけこのテストでは関係するとわかる
  23. Lazy setup func (s *server) handleTemplate(file string...) http.HandleFunc { var

    ( init sync.Once tpl *template.Template tplerr error ) return func(w http.ResposeWriter, r *http.Request) { init.Do(func() { tpl, tplerr = template.ParseFiles(files...) }) if tplerr != nil { // return error } // use template } } 重い処理を呼ばれるまで sync.Once で遅らせる GAE を利⽤する場合などで起動時間を速くしたい場合に有効
  24. 残りは元スライド、ライブブログで

  25. matryer/is is ... ? I call it “Testify off steroids”

    :) https://gophers.slack.com/archives/C0528UE9X/p1564348834304100?thread_ts=1564339225.294700&cid=C0528UE9X
  26. matryer/is func Test(t *testing.T) { is := is.New(t) signedin, err

    := isSignedIn(ctx) is.NoErr(err) // isSignedIn error is.Equal(signedin, true) // must be signed in body := readBody(r) is.True(strings.Contains(body, "Hi there")) } https://github.com/matryer/is#usage
  27. トークの感想 だいたい似たよう感じに作っているので安⼼できた 業務で HTTP sevice を作ることはほとんどないが、 HTTP service 以外を書く時でも 参考にできることがあった

    最初に挙げていた重要な要素など testify を置き換えたい
  28. 参考リンク Slide https://gophers.slack.com/archives/C0528UE9X/p1564339225294700 このレスに is の説明もあります 元になったブログ記事 https://medium.com/statuscode/how-i-write-go-http-services-after-seven- years-37c208122831 LiveBlog

    https://about.sourcegraph.com/go/gophercon-2019-how-i-write-http-web- services-after-eight-years