$30 off During Our Annual Pro Sale. View Details »

GopherCon 2019 Report

GopherCon 2019 Report

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

upamune / Yu SERIZAWA

August 20, 2019
Tweet

More Decks by upamune / Yu SERIZAWA

Other Decks in Programming

Transcript

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

    Ryer 出典: https://medium.com/@matryer
  2. Mat Ryer Blog medium.com/@matryer Podcast Go Time Books Go ⾔語による

    Web アプリケーション開発 Go Programming Blueprints OSS BitBar Testify Gopherize.me etc...
  3. 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 では依存をセットアップしない テストのため 多くなければ引数でとっても良い ルーティングだけセットアップする
  4. 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 からどのハンドラーを利⽤しているか容易に特定できる
  5. 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 を引数で受け取る
  6. 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 という短い構造体名にできる
  7. 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 フィールドだけこのテストでは関係するとわかる
  8. 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 を利⽤する場合などで起動時間を速くしたい場合に有効
  9. matryer/is is ... ? I call it “Testify off steroids”

    :) https://gophers.slack.com/archives/C0528UE9X/p1564348834304100?thread_ts=1564339225.294700&cid=C0528UE9X
  10. 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