LoginSignup
0
0

More than 1 year has passed since last update.

goのhttpパッケージの一部を理解する

Posted at

初めに

参考になる記事がたくさんあるので、まずリンクを貼る

目的

自分はあまり理解力が高くないので、記事を見るだけでは理解できなかったりする。
参考になる記事たちを見て、改めて自分の中で整理してこの記事でアウトプットすることで自分の理解を深める

下記サンプルコードをもとに理解を深める

main.go
package main

import (
    "net/http"

    "github.com/koga456/sample-api/controller"
    "github.com/koga456/sample-api/model/repository"
)

var tr = repository.NewTodoRepository()
var tc = controller.NewTodoController(tr)
var ro = controller.NewRouter(tc)

func main() {

    server := http.Server{
        Addr: ":8080",
    }
    http.HandleFunc("/todos/", ro.HandleTodosRequest)
    server.ListenAndServe()
}

コードリーディング

server := http.Server{
Addr: ":8080",
}

server変数にhttpパッケージのServer型にAddrのみ指定して代入

http.HandleFunc("/todos/", ro.HandleTodosRequest)

func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
    DefaultServeMux.HandleFunc(pattern, handler)
}

pattern(パス)とfunc(ResponseWriter, *Request)型のhandlerを引数にDefaultServeMuxのHandleFuncメソッドを実行している

// DefaultServeMux is the default ServeMux used by Serve.
var DefaultServeMux = &defaultServeMux

var defaultServeMux ServeMux

DeualtServeMuxはServeMux型の変数。
要するにhttp.HandleFuncはServeMux型をレシーバにもつHandleFuncメソッドを実行している。

// HandleFunc registers the handler function for the given pattern
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request))

HandleFunc(httpパッケージのServeMux型をレシーバにもつHandleFuncメソッド)

ServeMux型をレシーバに持つメソッドであり、pattern(/todos/)にhandler関数を登録(httpパッケージのServeMux型をレシーバに持つHandleメソッドを呼び出し)する

serveMux型,muxEntry型

type ServeMux struct {
    mu    sync.RWMutex
    m     map[string]muxEntry
    es    []muxEntry // slice of entries sorted from longest to shortest.
    hosts bool       // whether any patterns contain hostnames
}

type muxEntry struct {
    h       Handler
    pattern string
}


http.ServeMux.Handleは何をするのか

ソースコード
// Handle registers the handler for the given pattern.
// If a handler already exists for pattern, Handle panics.
func (mux *ServeMux) Handle(pattern string, handler Handler) {
    mux.mu.Lock()
    defer mux.mu.Unlock()

    if pattern == "" {
        panic("http: invalid pattern")
    }
    if handler == nil {
        panic("http: nil handler")
    }
    if _, exist := mux.m[pattern]; exist {
        panic("http: multiple registrations for " + pattern)
    }

    if mux.m == nil {
        mux.m = make(map[string]muxEntry)
    }
    e := muxEntry{h: handler, pattern: pattern}
    mux.m[pattern] = e
    if pattern[len(pattern)-1] == '/' {
        mux.es = appendSorted(mux.es, e)
    }

    if pattern[0] != '/' {
        mux.hosts = true
    }
}

pattern(パス)に対応づけてmux[string]muxEntryとして登録している

mux.Handle(pattern, HandlerFunc(handler))

handler(func ResponseWriter, *Request)をHandlerFunc型に変換してから渡すことで
func (m *ServeMux) Handle(pattern string, handler Handler)のHandler型に納めている

HandlerFunc型,Handler型
type HandlerFunc func(ResponseWriter, *Request)

func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request)

type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}


HandlerFunc型はServeHttpメソッドを実装していて、 Handlerはインターフェースであり、ServeHttpを実装していることが求められていることがわかる

上記HandlerFunc型に変換しているのはServeHttpを実装させるため、実装していればHandler Interfaceに収まる。

server.ListenAndServe()

先ほど定義したserver変数のListenAndServeメソッドを実行している。

// ListenAndServe listens on the TCP network address srv.Addr and then calls Serve to handle requests on incoming connections.
// Accepted connections are configured to enable TCP keep-alives.

func (srv *Server) ListenAndServe() error

server型 他にもたくさんあるけど、よく使う?ものだけ抜粋

type Server struct {
    // Addr optionally specifies the TCP address for the server to listen on,
    // in the form "host:port". If empty, ":http" (port 80) is used.
    // The service names are defined in RFC 6335 and assigned by IANA.
    // See net.Dial for details of the address format.
    Addr string

    Handler Handler // handler to invoke, http.DefaultServeMux if nil
}

今回、server型のAddrのみ指定して、Handlerは指定しなかったため、http.DefaultServeMuxになる

DefaultServeMuxについては上に書いたとおり、HandleFuncが呼び出されていく

まとめ • 感想

今回色々な記事を見て頭に入らなかった原因がこの記事を書いている内にわかった

  • 公式のdocを全然見てなかった

  下記に理由はあるが、公式のドキュメントを読んでいなかった

  • メソッドについての理解が足りていなかった

  A Tour of Goをさらっと流し読みして、分かった気になっていたが、メソッド関数と関数の違いを分かっていなかったのでドキュメントを見てもイマイチピンと来なかった

後は書いている内に理解が深まっていった(わかっていないところがわかるようになった)ので、いい記事を書こうとは思わず、誰が見るわけでもないと思って気軽に書いていきたい

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0