溫馨提示×

Golang日志如何實現異步寫入

小樊
34
2025-08-16 10:03:21
欄目: 編程語言

在Golang中,實現異步日志寫入可以通過使用goroutine和channel來實現。下面是一個簡單的示例,展示了如何創建一個異步日志記錄器:

package main

import (
	"fmt"
	"os"
	"sync"
	"time"
)

type LogEntry struct {
	Timestamp time.Time
	Message   string
}

type AsyncLogger struct {
	logChan chan LogEntry
	wg      sync.WaitGroup
	done    chan bool
}

func NewAsyncLogger(bufferSize int) *AsyncLogger {
	logger := &AsyncLogger{
		logChan: make(chan LogEntry, bufferSize),
		done:    make(chan bool),
	}
	logger.wg.Add(1)
	go logger.writer()
	return logger
}

func (l *AsyncLogger) writer() {
	defer l.wg.Done()

	for {
		select {
		case entry := <-l.logChan:
			file, err := os.OpenFile("async_log.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
			if err != nil {
				fmt.Println("Error opening log file:", err)
				continue
			}
			fmt.Fprintf(file, "%s - %s\n", entry.Timestamp.Format(time.RFC3339), entry.Message)
			file.Close()
		case <-l.done:
			return
		}
	}
}

func (l *AsyncLogger) Log(message string) {
	entry := LogEntry{
		Timestamp: time.Now(),
		Message:   message,
	}
	l.logChan <- entry
}

func (l *AsyncLogger) Close() {
	close(l.done)
	l.wg.Wait()
}

func main() {
	logger := NewAsyncLogger(100)

	go func() {
		for i := 0; i < 10; i++ {
			logger.Log("Log entry #" + fmt.Sprintf("%d", i))
			time.Sleep(1 * time.Second)
		}
	}()

	time.Sleep(15 * time.Second)
	logger.Close()
}

在這個示例中,我們創建了一個名為AsyncLogger的結構體,它包含一個用于存儲日志條目的channel(logChan),一個sync.WaitGroupwg)以及一個用于通知寫入器goroutine退出的channel(done)。

NewAsyncLogger函數接收一個參數bufferSize,用于設置logChan的緩沖區大小。然后,它創建一個新的AsyncLogger實例,并啟動一個名為writer的goroutine,該goroutine負責將日志條目寫入文件。

Log方法用于向logChan發送新的日志條目。當調用此方法時,它將創建一個新的LogEntry實例,并將其發送到logChan。

Close方法用于關閉done channel并等待writer goroutine完成。在程序結束時,應調用此方法以確保所有日志條目都已正確寫入文件。

main函數中,我們創建了一個AsyncLogger實例,并啟動了一個goroutine,該goroutine每隔1秒記錄一條日志。然后,我們讓主goroutine等待15秒,以確保所有日志條目都已記錄。最后,我們調用Close方法關閉日志記錄器。

0
亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女