LoginSignup
0
1

More than 3 years have passed since last update.

【Go】ServeMux について

Last updated at Posted at 2020-08-21

※注意: この記事ははあくまで個人学習用に整理しただけの記事で、内容としては不完全なものになります。読んでも参考にならない可能性が高いです。

golang を勉強し始めてたが、ServeMux がいまいちわからないのでまとめる

ServeMux とは

公式ドキュメントには以下のように書いてある
https://golang.org/pkg/net/http/#ServeMux

ServeMux is an HTTP request multiplexer. It matches the URL of each incoming request against a list of registered patterns and calls the handler for the pattern that most closely matches the URL.
ServeMuxはHTTPリクエストマルチプレクサーです。各着信リクエストのURLを登録済みパターンのリストと照合し、URLに最も近いパターンのハンドラーを呼び出します。

マルチプレクサー というのは。。。?

マルチプレクサ、多重器、多重装置、多重化装置、合波器(multiplexer)は、ふたつ以上の入力をひとつの信号として出力する機構である。通信分野では多重通信の入口の装置、電気・電子回路では複数の電気信号をひとつの信号にする回路である。しばしばMUX等と略される。

複数の信号を入力として受け取り、1つの信号にして出力するもののようだ。http リクエストのマルチプレクサーが ServeMux ということらしい。routing を実現するための構造体のようだ。

ServeMux は以下のような構造になっている。


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
}

sync.RWMutex ? muxEntry ? また未知のものが出てきた。。

sync.RWMutex とは

A RWMutex is a reader/writer mutual exclusion lock. The lock can be held by an arbitrary number of readers or a single writer. The zero value for a RWMutex is an unlocked mutex.
RWMutexは、リーダー/ライターの相互排他ロックです。ロックは、任意の数のリーダーまたは単一のライターが保持できます。 RWMutexのゼロ値は、ロックされていないミューテックスです。

正確には理解できていないが、リーダー/ライターの相互排他ロックとのこと。
以下のような構造になっている。
https://golang.org/src/sync/rwmutex.go?s=987:1319#L18


type RWMutex struct {
    w           Mutex  // held if there are pending writers
    writerSem   uint32 // semaphore for writers to wait for completing readers
    readerSem   uint32 // semaphore for readers to wait for completing writers
    readerCount int32  // number of pending readers
    readerWait  int32  // number of departing readers
}

また Mutex というわからないものが出てきた。

sync.Mutex とは

A Mutex is a mutual exclusion lock.
The zero value for a Mutex is an unlocked mutex.
Mutexは相互排他ロックです。
ミューテックスのゼロ値はロックされていないミューテックスです。

ロックについては以下の記事がわかりやすかった
Go でロックする
sync.Mutex【Go】
A Tour of Go
複数の goroutines から並行処理で、同じ変数を変更したりする際にロックが重要になるとのこと。
RWMutex はそのリーダー/ライター版ってことかな?

そして muxEntry についても確認

http.muxEntry とは

http パッケージ内に以下のように定義されている

type muxEntry struct {
    h       Handler
    pattern string
}

Handler と URL パターンを持った構造体だ。

muxEntry は、以下の ServeMux の Handle method で使用されている。
https://golang.org/src/net/http/server.go?h=muxEntry#L2420

// 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) // フィールド m にmake(map[string]muxEntry) が代入され 
    }
    // muxEntry 構造体を h handler, pattern pattern で初期化した e 変数を作成
    e := muxEntry{h: handler, pattern: pattern}
    mux.m[pattern] = e // mux.m[pattern]に代入されている。
    if pattern[len(pattern)-1] == '/' {
        mux.es = appendSorted(mux.es, e)
    }

    if pattern[0] != '/' {
        mux.hosts = true // パターンにホスト名が含まれているかどうか
    }
}

func appendSorted(es []muxEntry, e muxEntry) []muxEntry {
    n := len(es)
    i := sort.Search(n, func(i int) bool {
        return len(es[i].pattern) < len(e.pattern)
    })
    if i == n {
        return append(es, e)
    }
    // we now know that i points at where we want to insert
    es = append(es, muxEntry{}) // try to grow the slice in place, any entry works.
    copy(es[i+1:], es[i:])      // Move shorter entries down
    es[i] = e
    return es
}

mux.esは

slice of entries sorted from longest to shortest.
最長から最短にソートされたエントリのスライス。

とのこと。appendSorted でソートしたエントリのスライスを生成して、mux.esへ格納している

なぜ ServeMux の Handle メソッドを実装した際に sync.RWMutex で lock する必要があるのかは読み解けなかった。。。

まとめると、

ServeMux は

  • reader / writer ロックの為の sync.RWMutex
  • URL と Hander の map
  • sort した URL の配列
  • パターンにホスト名が含まれているかどうかのフラグ

以上を保有した構造体だった。

あんまりわかってないけど、一旦そういうものと整理しておく。

0
1
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
1