承上一篇,我們從melody.Session 開始做研究。
首先找到它的位置。
// Session wrapper around websocket connections.
type Session struct {
Request *http.Request
Keys map[string]interface{}
conn *websocket.Conn
output chan *envelope
melody *Melody
open bool
rwmutex *sync.RWMutex
}
ok,Session 是一個struct的型態,我們來看一下內容有什麼,主要抓可能也是struct的東西來看就好了。
下面這幾個是別的package的東西,就先乎略不看。
*http.Request
*websocket.Conn
*sync.RWMutex
值得在乎的就只剩兩者,envelope先不管是被當作channel使用的型態。
output chan *envelope
melody *Melody
這兩個結構分別放在以下檔案
envelop.go
type envelope struct {
t int
msg []byte
filter filterFunc
}
melody.go
type Melody struct {
Config *Config
Upgrader *websocket.Upgrader
messageHandler handleMessageFunc
messageHandlerBinary handleMessageFunc
messageSentHandler handleMessageFunc
messageSentHandlerBinary handleMessageFunc
errorHandler handleErrorFunc
closeHandler handleCloseFunc
connectHandler handleSessionFunc
disconnectHandler handleSessionFunc
pongHandler handleSessionFunc
hub *hub
}
再繼續尋了一遍,有相關又是struct的結構,有*Config 和 *hub
Config
// Config melody configuration struct.
type Config struct {
WriteWait time.Duration // Milliseconds until write times out.
PongWait time.Duration // Timeout for waiting on pong.
PingPeriod time.Duration // Milliseconds between pings.
MaxMessageSize int64 // Maximum size in bytes of a message.
MessageBufferSize int // The max amount of messages that can be in a sessions buffer before it starts dropping them.
}
hub
type hub struct {
sessions map[*Session]bool
broadcast chan *envelope
register chan *Session
unregister chan *Session
exit chan *envelope
open bool
rwmutex *sync.RWMutex
}
我們總共找到5個struct,此時就可以來猜測它們的關係了。
envelope 和 Config分析起來,只是個資料儲存用途,我們就不是為業務主體,而且只關心業務主體。
於是重新再整理,業務主體有如下:
到這邊,發現很有趣的狀況,因為Session是我們直接接觸到的最末端型態,Session應該在下游,而melody應該在最上游。
關係是
melody --> hub --> Session
下面的不知上面的,如hub不知道有melody,session不知道有hub,但是最下游的Session,卻又能直接關心最上游的melody。
Session --> melody
三者業務主體好比銜尾蛇一樣,頭咬著對方尾巴,卻不知道尾巴被誰咬著,但整體卻連接在一起,形成一個圓圈。
為什麼有這樣的設計呢?
其實並不是melody這個package特地稀奇古怪的這樣寫,source code或其他一樣open source也常出現的結構,起初筆者還不太懂這種模式和背後的用意,覺得十分困惑。
其實也不是太難的東西,但沒人點破實在是個麻煩的障礙,下篇筆者試著來為大家分享如何解釋這樣的設計,希望能夠幫助一些跟筆者當初一樣,遇到卡關障礙的開發者。