MST

星途 面试题库

面试题:Go语言中如何设置不同日志级别的输出

在Go语言日志包的使用场景下,假设我们有DEBUG、INFO、WARN、ERROR这几种日志级别,描述一下如何实现根据不同日志级别输出日志到控制台或者文件,并且在程序运行时能够动态调整日志级别。
37.0万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
  1. 定义日志级别: 首先定义一个表示日志级别的枚举类型。
    type LogLevel int
    
    const (
        DEBUG LogLevel = iota
        INFO
        WARN
        ERROR
    )
    
  2. 初始化日志输出: 初始化日志输出到控制台和文件。使用log包和os包。
    var (
        consoleLogger *log.Logger
        fileLogger   *log.Logger
        logLevel     LogLevel
    )
    
    func init() {
        // 初始化控制台日志
        consoleLogger = log.New(os.Stdout, "", log.LstdFlags)
        // 创建日志文件
        logFile, err := os.OpenFile("app.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
        if err!= nil {
            consoleLogger.Fatalf("Failed to open log file: %v", err)
        }
        fileLogger = log.New(logFile, "", log.LstdFlags)
        logLevel = INFO // 默认日志级别为INFO
    }
    
  3. 实现日志输出函数: 根据不同的日志级别输出日志到控制台和文件。
    func logMessage(level LogLevel, format string, v...interface{}) {
        if level < logLevel {
            return
        }
        var prefix string
        switch level {
        case DEBUG:
            prefix = "[DEBUG]"
        case INFO:
            prefix = "[INFO]"
        case WARN:
            prefix = "[WARN]"
        case ERROR:
            prefix = "[ERROR]"
        }
        message := fmt.Sprintf(prefix+ " "+format, v...)
        consoleLogger.Println(message)
        fileLogger.Println(message)
    }
    
  4. 动态调整日志级别: 可以通过HTTP接口或者配置文件来动态调整日志级别。
    • 通过HTTP接口
      http.HandleFunc("/setloglevel", func(w http.ResponseWriter, r *http.Request) {
          levelStr := r.URL.Query().Get("level")
          var newLevel LogLevel
          switch levelStr {
          case "DEBUG":
              newLevel = DEBUG
          case "INFO":
              newLevel = INFO
          case "WARN":
              newLevel = WARN
          case "ERROR":
              newLevel = ERROR
          default:
              http.Error(w, "Invalid log level", http.StatusBadRequest)
              return
          }
          logLevel = newLevel
          fmt.Fprintf(w, "Log level set to %s", levelStr)
      })
      log.Fatal(http.ListenAndServe(":8080", nil))
      
    • 通过配置文件: 可以使用viper等库读取配置文件。
      func loadConfig() {
          viper.SetConfigName("config")
          viper.SetConfigType("yaml")
          viper.AddConfigPath(".")
          err := viper.ReadInConfig()
          if err!= nil {
              consoleLogger.Fatalf("Error reading config file: %v", err)
          }
          levelStr := viper.GetString("loglevel")
          var newLevel LogLevel
          switch levelStr {
          case "DEBUG":
              newLevel = DEBUG
          case "INFO":
              newLevel = INFO
          case "WARN":
              newLevel = WARN
          case "ERROR":
              newLevel = ERROR
          default:
              newLevel = INFO
          }
          logLevel = newLevel
      }
      

使用示例:

func main() {
    logMessage(DEBUG, "This is a debug message")
    logMessage(INFO, "This is an info message")
    logMessage(WARN, "This is a warning message")
    logMessage(ERROR, "This is an error message")
}