我正在嘗試使用go-json-rest在 golang 中編寫 REST 服務該服務的目的只是將接收到的數據轉換為 CSV 并記錄下來。由于負載可能很重,我想使用 goroutines 進行日志記錄。目前我已經創建了四個 LogWorkers(goroutine) 每個 goroutine 將把 CSV 記錄到單獨的文件中。當我執行代碼時,日志總是從最后一個 goroutine 觸發。我看到在我的日志文件夾中創建了一個來自第四個例程的文件。這是我的服務器代碼package mainimport ( "github.com/ant0ine/go-json-rest/rest" "log" "net/http" "strconv" "time")const workerCount = 4var evChannel = make(chan Event)var workers = make([]*LogWorker, workerCount)const maxLogFileSize = 100 // In MBconst maxLogFileBackups = 30const maxLogFileAge = 5const logFileName = "/home/sam/tmp/go_logs/event_"func main() { // Initialize workers // Four workers is being created for i := 0; i < workerCount; i++ { var fileName = logFileName + strconv.Itoa(i) workers[i] = NewLogWorker(fileName, maxLogFileSize, maxLogFileBackups, maxLogFileAge) go workers[i].Work(evChannel) } // Initialize REST API api := rest.NewApi() //api.Use(rest.DefaultDevStack...) api.Use(rest.DefaultCommonStack...) router, err := rest.MakeRouter( rest.Post("/events", StoreEvents), ) if err != nil { log.Fatal(err) } api.SetApp(router) log.Fatal(http.ListenAndServe(":4545", api.MakeHandler()))}func StoreEvents(w rest.ResponseWriter, r *rest.Request) { event := Event{} err := r.DecodeJsonPayload(&event) if err != nil { rest.Error(w, err.Error(), http.StatusInternalServerError) return } // TODO : Add validation if needed // Add code to parse the request and add further information to event // log.Println() select { case evChannel <- event: case <- time.After(5 * time.Second): // throw away the message, so sad } // evChannel <- event //log.Println(Csv(event)) w.WriteHeader(http.StatusOK)}請注意 event 是一個包含一些字符串字段的結構。SO 中已經有一個類似的問題。當我嘗試在playground執行 goroutine 時,它仍然打印上次goroutine的值。提供的答案有一些等待。完成。由于我的工人需要連續運行,我認為我不能使用它。請幫我找出為什么我的所有 goroutines (LogWorkers) 都沒有被使用?
1 回答

瀟湘沐
TA貢獻1816條經驗 獲得超6個贊
您正在每個 goroutine 中設置日志包的默認全局記錄器輸出。
您可能想要做更多類似的事情:
func (lw *LogWorker) Work(evChannel chan Event) {
fmt.Println(lw.FileName)
lg := log.New(&lumberjack.Logger {
Filename: lw.FileName,
MaxSize: lw.MaxSize,
MaxBackups: lw.MaxBackups,
MaxAge: lw.MaxAge,
}, "", 0)
for {
event := <- evChannel
lg.Println(Csv(event))
}
}
這將為每個 goroutine 提供一個記錄器。
在您的版本中,您可能只有最后一個要執行(可能是最后一個 goroutine 生成,但不能保證)
為了進一步改進,您可能還希望將 for 循環寫為:
for event := range evChannel {
lg.Println(Csv(event))
}
這樣,它會在通道關閉時終止 goroutine,而不是在關閉通道中的空值上旋轉。 請參閱此處以供參考
- 1 回答
- 0 關注
- 207 瀏覽
添加回答
舉報
0/150
提交
取消