Go标准库日志打印及同时输出到控制台与文件

目录
  • 打印
  • log包
  • 如何输出日志到文件?
  • 如何同时输出到控制台和文件?
  • 附:日志切割(按文件大小切割、按日期切割)
  • 总结

打印

在使用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()//拿到文件大小

日期切割:

拿到文件的名称或者检查下有没有当天的日志文件,没有就创建新增。

总结

到此这篇关于Go标准库日志打印及同时输出到控制台与文件的文章就介绍到这了,更多相关Go标准库日志打印及输出内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Go实现整合Logrus实现日志打印

    目录 1 初步使用 2 增加标签WithFields 3 配置常见参数 4 输出日志到文件 5 利用Hooks将日志输出到其他地方 Github:github.com/sirupsen/lo… 1 初步使用 package main import (   "context"   "github.com/sirupsen/logrus" ) ​ func main() {   method0() } func method0() {   logger:= logrus

  • Go标准库日志打印及同时输出到控制台与文件

    目录 打印 log包 如何输出日志到文件? 如何同时输出到控制台和文件? 附:日志切割(按文件大小切割.按日期切割) 总结 打印 在使用go写一些小程序时,我们没必要引入额外的包,直接使用fmt标准包打印即可: import "fmt" func main() { fmt.Println("line1") fmt.Print("line2") fmt.Printf("line%d \n", 3) str1 := fmt.Spr

  • 源码分析SpringMvc日志打印被忽略输出问题

    目录 1.写在前面 2.问题引出 3.截取源码分析 4.截取问题处理 1.写在前面 在java的开发过程中,涉及到java web的开发,基本上都是走spring这一套了. 我们之前一般来说,都会说mvc:Model(模型业务).View(视图界面).Controller(控制器).这个学习java开发的,应该都懂吧,这里就不多说了. 这里,我们先着重解析下Controller: Controller控制器是指控制器接受用户的输入并调用模型和视图去完成用户的需求,控制器本身不输出任何东西和做任何

  • python 信息同时输出到控制台与文件的实例讲解

    python编程中,往往需要将结果用print等输出,如果希望输出既可以显示到IDE的屏幕上,也能存到文件中(如txt)中,该怎么办呢? 方法1 可通过日志logging模块输出信息到文件或屏幕.但可能要设置log的level或输出端,对于同时需要记录debug error等信息的较为合适,官方教程推荐学习用更规范的logger来操作. 例如,可参考来自官网的这段代码. import logging logging.basicConfig(filename='log_examp.log',lev

  • 解析PHP SPL标准库的用法(遍历目录,查找固定条件的文件)

    <?php  class RecursiveFileFilterIterator extends FilterIterator {      // 满足条件的扩展名      protected $ext = array('jpg','gif'); /**       * 提供 $path 并生成对应的目录迭代器       */      public function __construct($path) {          parent::__construct(new Recursiv

  • Python 使用 prettytable 库打印表格美化输出功能

    pip install prettytable 每次添加一行 from prettytable import PrettyTable # 默认表头:Field 1.Field 2... # 添加表头 table = PrettyTable(["URL", "参数", "值"]) # add_row 添加一行数据 table.add_row(["http://aaa.com", "raskv", "

  • Python3标准库之threading进程中管理并发操作方法

    1. threading进程中管理并发操作 threading模块提供了管理多个线程执行的API,允许程序在同一个进程空间并发的运行多个操作. 1.1 Thread对象 要使用Thread,最简单的方法就是用一个目标函数实例化一个Thread对象,并调用start()让它开始工作. import threading def worker(): """thread worker function""" print('Worker') threads

  • 200个Python 标准库总结

    目录 1.文本 2.数学 3.函数式编程 4.文件与目录 5.持久化 6.压缩 7.加密 8.操作系统工具 9.并发 10.进程间通信 11.互联网 12.互联网协议与支持 13.多媒体 14.国际化 15.编程框架 16.Tk图形用户接口 17.开发工具 18.调试 19.运行时 20.解释器 21.导入模块 22.Python语言 23.其他 24.Windows相关 25.Unix相关 1.文本 string:通用字符串操作 re:正则表达式操作 difflib:差异计算工具 textwr

  • Python标准库中的logging用法示例详解

    目录 1.logging的介绍 2.简单用法示例 3.日志级别 4.打印格式的各个参数 5.日志输出到指定文件 6.日志回滚(按照文件大小滚动) 7.日志回滚(按照时间滚动) 1.logging的介绍 logging是Python标准库中记录常用的记录日志库,通过logging模块存储各种格式的日志,主要用于输出运行日志,可以设置输出日志的等级.日志保存路径.日志文件回滚等. 2.简单用法示例 首先创建一个logger.py的文件,其里面的代码如下所示: import logging # 1.创

  • python学习——内置函数、数据结构、标准库的技巧(推荐)

    我作为一名python初学者,为了强化记忆有必要把看过的一些优秀的文章中一些技巧通过notebook的方式练习一次.我认为这么做有几个优点:一来加深印象:二来也可以将学习过的内容保存方便日后查阅:第三也可以培养我写博的习惯(一直都没那个习惯) jupyter notebook格式的文件github下载: 身为程序员除了需要具备解决问题的思路以外,代码的质量和简洁性也很关键,今天又学习到了一些觉得自己很高级的内容跟大家分享,内容包括: Python内置函数开始 Python对数据结构的天然支持 P

  • Python标准库itertools的使用方法

    Python标准库itertools模块介绍 itertools是python内置的模块,使用简单且功能强大,这里尝试汇总整理下,并提供简单应用示例:如果还不能满足你的要求,欢迎加入补充. 使用Python标准库itertools只需简单一句导入:import itertools chain() 与其名称意义一样,给它一个列表如 lists/tuples/iterables,链接在一起:返回iterables对象. letters = ['a', 'b', 'c', 'd', 'e', 'f']

随机推荐