網站首頁 編程語言 正文
打印
在使用go寫一些小程序時,我們沒必要引入額外的包,直接使用fmt標準包打印即可:
import "fmt" func main() { fmt.Println("line1") fmt.Print("line2") fmt.Printf("line%d \n", 3) str1 := fmt.Sprintln("hello", 3) str2 := fmt.Sprint("hello ", 1, " 2") str3 := fmt.Sprintf("hello %d", 1) fmt.Print(str1, str2, str3) }
line1
line2line3?
hello 3
hello 1 2hello 1
那么,有些場景下,我們希望能同時打印到日志文件中要怎么辦呢?
log包
標準庫提供了log組件,用法和fmt一致,有3種方式:
import “log" func main() { log.Println("line1") log.Print("line2") log.Printf("line%d \n", 3) }
和fmt的區別就是多了時間:
2021/08/25 17:23:47 line1
2021/08/25 17:23:47 line2
2021/08/25 17:23:47 line3?
我們通過SetFlag函數,可以設置打印的格式:
// For example, flags Ldate | Ltime (or LstdFlags) produce, // 2009/01/23 01:23:23 message // while flags Ldate | Ltime | Lmicroseconds | Llongfile produce, // 2009/01/23 01:23:23.123123 /a/b/c/d.go:23: message const ( Ldate = 1 << iota // the date in the local time zone: 2009/01/23 Ltime // the time in the local time zone: 01:23:23 Lmicroseconds // microsecond resolution: 01:23:23.123123. assumes Ltime. Llongfile // full file name and line number: /a/b/c/d.go:23 Lshortfile // final file name element and line number: d.go:23. overrides Llongfile LUTC // if Ldate or Ltime is set, use UTC rather than the local time zone Lmsgprefix // move the "prefix" from the beginning of the line to before the message LstdFlags = Ldate | Ltime // initial values for the standard logger )
比如,我們只需要時間和文件名:
import “log" func main() { log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile) log.Println("line1") log.Print("line2") log.Printf("line%d \n", 3) }
此時,再次運行,則會打印文件和行號:
2021/08/25 17:27:56 mod_unread_redis.go:32: line1
2021/08/25 17:27:56 mod_unread_redis.go:33: line2
2021/08/25 17:27:56 mod_unread_redis.go:34: line3
如何輸出日志到文件?
log包使用非常簡單,默認情況下,只會輸出到控制臺。
我們可以使用SetOutput改變輸出流,比如輸出到文件。
先來看一下函數原型,其接收一個io.Writer接口:
// SetOutput sets the output destination for the standard logger. func SetOutput(w io.Writer) { // ... }
那么,我們就可以創建一個文件流設置一下就行了。
// 創建、追加、讀寫,777,所有權限 f, err := os.OpenFile("log.log", os.O_CREATE|os.O_APPEND|os.O_RDWR, os.ModePerm) if err != nil { return } defer func() { f.Close() }() log.SetOutput(f)
此時,在運行,我們發現日志會輸出到文件,但是控制臺沒有任何東西輸出了。
如何同時輸出到控制臺和文件?
標準庫io包中,有一個MultiWriter,可以把文件流和控制臺標準輸出流整合到一個io.Writer上,其實現上就是一個數組,在執行寫操作時,遍歷數組:
// MultiWriter creates a writer that duplicates its writes to all the // provided writers, similar to the Unix tee(1) command. // // Each write is written to each listed writer, one at a time. // If a listed writer returns an error, that overall write operation // stops and returns the error; it does not continue down the list. func MultiWriter(writers ...Writer) Writer { allWriters := make([]Writer, 0, len(writers)) for _, w := range writers { if mw, ok := w.(*multiWriter); ok { allWriters = append(allWriters, mw.writers...) } else { allWriters = append(allWriters, w) } } return &multiWriter{allWriters} } // 重寫io.Writer的Write函數函數,本質上就是遍歷數組,比較巧妙 func (t *multiWriter) Write(p []byte) (n int, err error) { for _, w := range t.writers { n, err = w.Write(p) if err != nil { return } if n != len(p) { err = ErrShortWrite return } } return len(p), nil }
使用方式如下:
func main() { f, err := os.OpenFile("log.log", os.O_CREATE|os.O_APPEND|os.O_RDWR, os.ModePerm) if err != nil { return } defer func() { f.Close() }() // 組合一下即可,os.Stdout代表標準輸出流 multiWriter := io.MultiWriter(os.Stdout, f) log.SetOutput(multiWriter) log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile) log.Println("line1") log.Print("line2") log.Printf("line%d \n", 3) }
此時,再運行,則會同時輸出到控制臺和文件中。
2021/08/25 17:38:02 mod_unread_redis.go:42: line1
2021/08/25 17:38:02 mod_unread_redis.go:43: line2
2021/08/25 17:38:02 mod_unread_redis.go:44: line3?
附:日志切割(按文件大小切割、按日期切割)
其實就是每次記錄文件的大小,超過了就重新寫一個文件。
通過Stat()函數拿到文件的一些信息
open, _:= os.Open("文件名") stat, _, := open.Stat() stat.Size()//拿到文件大小
日期切割:
拿到文件的名稱或者檢查下有沒有當天的日志文件,沒有就創建新增。
總結
原文鏈接:https://blog.csdn.net/xmcy001122/article/details/119916227
相關推薦
- 2022-12-23 C++中關于union的使用方法說明_C 語言
- 2021-12-18 linux下安裝redis圖文詳細步驟_Redis
- 2022-11-26 使用HttpClient消費ASP.NET?Web?API服務案例_實用技巧
- 2022-11-30 jQuery中隱藏元素的hide方法及說明_jquery
- 2022-10-14 Linux環境conda虛擬環境中python解釋器對應問題 + 解決后pip install 路徑
- 2022-11-06 Nginx如何配置多個服務域名解析共用80端口詳解_nginx
- 2023-01-03 Android?輸入框被擋問題完美解決方案_Android
- 2024-02-17 BDD - Python Behave 用戶自定義配置文件
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支