1 回答

TA貢獻1820條經驗 獲得超10個贊
這種方法存在幾個問題。
首先,您的代碼包含數據競爭:每個 TCP 連接都由一個單獨的 goroutine 提供服務,并且它們都試圖同時修改切片。
go build -race您可能會嘗試使用(或go install -race— 無論您使用什么)構建代碼,并看到它因啟用的運行時檢查而崩潰。
這個很容易修復。最直接的方法是在類型中添加一個互斥變量ClientList:
type ClientList struct {
mu sync.Mutex
clients []*Client
}
…并使類型的方法在改變字段時保持互斥量clients,如下所示:
func (cList *ClientList) AddClient(cl *Client) {
cList.mu.Lock()
defer cList.mu.Unlock()
cList.clients = append(cList.clients, o)
}
(如果你曾經遇到過你的ClientList類型的典型使用模式是頻繁調用只讀取包含列表的方法,你可以開始使用sync.RWLock允許多個并發讀取器的類型。)
其次,我將“識別”客戶端的部分從處理函數中分離出來。至此,在handler中,如果識別失敗,handler退出,但client不會退市。
我會說最好預先識別它,并且只有在認為客戶沒問題時才運行處理程序。
此外,值得RemoveClient在處理程序主體的頂部添加一個延遲調用,以便在處理程序完成時正確地取消列出客戶端。
IOW,我希望看到這樣的事情:
func (cl *Client) HandleClient(cList *ClientList) {
defer cl.Conn.Close()
err := cl.Identify()
if err != nil {
log.Println(err)
return
}
cList.AddClient(cl)
defer cList.RemoveClient(cl)
// ... the rest of the code
}
- 1 回答
- 0 關注
- 126 瀏覽
添加回答
舉報