使用runtime.Caller(1)记录错误日志

package main

import (
   "bufio"
   "database/sql"
   "fmt"
   "os"
   "path/filepath"
   "runtime"
   "time"
)

// Foo1
// @description 测试函数
// @return err error 错误对象,若无错误则为nil
func Foo1() (err error) {
   err = nil

   dsn := "username:password@tcp(localhost:3306)/database?charset=utf8mb4"
   _, err = sql.Open("mysql", dsn) // 说明:由于还未导入mysql驱动包,这里必然出错。
   if err != nil {
      WriteErrorLog(err, "error")
      return
   }

   return
}

// Foo2
// @description 求两数的商
// @param num1 int64 被除数
// @param num2 int64 除数
// @return divide int64 商
func Foo2(num1 int64, num2 int64) (divide int64) {
   // 使用defer和recover()实现捕获panic错误
   defer func() {
      err := recover()
      if err != nil {
         WriteErrorLog(err.(error), "panic")
         divide = 9527
      }
   }()

   divide = num1 / num2
   return
}

// WriteErrorLog
// @description 写错误日志
// @param err error 错误对象
// @param kind string 错误类型,可选值:error|panic
func WriteErrorLog(err error, kind string) {
   // 获取当前时间
   location, _ := time.LoadLocation("Asia/Shanghai")
   dateTime := time.Unix(time.Now().In(location).Unix(), 0).In(location).Format(time.DateTime)

   // 错误日志文件硬盘路径
   path, _ := filepath.Abs(".")
   log := path + "/error.log"

   content := "" // 日志内容
   _, file, line, ok := runtime.Caller(1)
   if ok {
      content = fmt.Sprintf("[%s][%s] %s in %s on line %d", dateTime, kind, err.Error(), file, line)
   } else {
      content = fmt.Sprintf("[%s][%s] %s", dateTime, kind, err.Error())
   }
   // 说明:file是调用WriteErrorLog()的文件,line是调用WriteErrorLog()所在行。

   // 打开日志文件(不存在则创建、只写、尾部追加)
   handle, _ := os.OpenFile(log, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)

   // 关闭日志文件
   defer func(handle *os.File) {
      _ = handle.Close()
   }(handle)

   // 写入日志文件
   writer := bufio.NewWriter(handle)
   _, _ = writer.WriteString(content + "\n")
   _ = writer.Flush()
}

func main() {
   err := Foo1()
   if err != nil {
      fmt.Println("连接数据库失败:" + err.Error()) // 连接数据库失败:sql: unknown driver "mysql" (forgotten import?)
   }

   num := Foo2(1024, 0)
   fmt.Println(num) // 9527
   // 说明:除数为0原本会报panic,但是由于Foo2()用了defer-recover捕获了panic错误,所以这里依然能正常执行。
}

// 执行以上代码后,会在错误日志文件看到以下两条错误信息:
// [2006-01-02 15:04:05][error] sql: unknown driver "mysql" (forgotten import?) in /go/src/main.go on line 22
// [2006-01-02 15:04:05][panic] runtime error: integer divide by zero in /go/src/main.go on line 39

Copyright © 2024 码农人生. All Rights Reserved