Go 语言 の 日志(读写文件和时间)



对切片的操作,是值类型的,对 map 的操作是指针类型的。对传值的效果也是一样的。

go 对文件的操作

对文件进行操作的时候,,如果是一行一行的读,建议使用 bufio 来实现。

  • 如果只是读,可以只使用 Open 这个方法,如果要是写就不行了。
  • 如果要写,使用 openfile 做个函数,使用指定的模式打开该文件。
package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
)

func main() {
	fileObej, err := os.Open("./test.go") // 读取文件,可以使用相对路径
	if err != nil {
		fmt.Println("open test.go failed") // 打印文件的时候出错了
		return
	}
	defer fileObej.Close() // 最后要关闭文件夹

	// 使用 buf 来读
	read := bufio.NewReader(fileObej) // 使用buf 来读

	for { // 一行一行的来读
		line, err := read.ReadString('\n') // 注意是字符
		if err == io.EOF {
			fmt.Println("文件读完了")
			break
		}
		if err != nil {
			fmt.Println("文件有错误", err) // 把错误打印出来
		}
		fmt.Println(line)
	}
}

对整个文件进行操作

package main

import (
	"fmt"
	"io/ioutil"
)

func main() {
	contents, err := ioutil.ReadFile("./test.go")
	if err != nil {
		fmt.Println("文件输出有错", err)
		return
	}
	fmt.Println(string(contents)) // 把二进制的文件转换成字符串
}


写数据操作

package main

import (
	"fmt"
	"os"
)

func main() {
	fileObej, err := os.OpenFile("./test.txt", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 02) // 可写或者创建

	if err != nil {
		fmt.Println("打开文件有错误", err)
		return
	}
	defer fileObej.Close() // 先检查打开错误,再说关闭的事情
	fileObej.WriteString("你好,我是test 文件夹")
}

time包

package main

import (
	"fmt"
	"time"
)

func main() {
	t := time.Now()
	fmt.Println(t)
	fmt.Println(t.Year())               // 年
	fmt.Println(t.Hour())               // 小时
	fmt.Println(t.Format("2006-01-02")) // 格式化输出,是按照go语言发明的时间声明的。
	fmt.Println("解析格式")
	fmt.Println(time.Parse("2006-01-02", "2008-15-4"))
	fmt.Println("打印时间戳")
	fmt.Println(t.Unix())     //时间戳
	fmt.Println(t.UnixNano()) // 毫秒的时间戳

	fmt.Println("暂停五秒")
	// 暂停1分钟再打印
	time.Sleep(5 * time.Second)

	// 把时间戳变成年
	fmt.Println("把时间戳再转变成年")
	tm := time.Unix(1618114441, 0)
	fmt.Println(tm) // 把年转换回来

	fmt.Println("时间相加")
	fmt.Println(t.Add(time.Hour * 24))
	fmt.Println("定时器")

	v := 0
	// 打印计时器(本质上是通道)
	timer := time.Tick(time.Second) // 一秒执行一次
	for t := range timer {
		v++
		if v > 10 {
			break
		}
		fmt.Println(t)
	}
}


// 输出
2021-04-11 14:03:35.7623396 +0800 CST m=+0.004965801
2021
14
2021-04-11
解析格式
0001-01-01 00:00:00 +0000 UTC parsing time "2008-15-4": month out of range
打印时间戳
1618121015
1618121015762339600
暂停一分钟
exit status 3221225786

D:\GoCode\src\pengzhao.xyz>go run test.go
2021-04-11 14:04:08.9291022 +0800 CST m=+0.003156501
2021
14
2021-04-11
解析格式
0001-01-01 00:00:00 +0000 UTC parsing time "2008-15-4": month out of range
打印时间戳
1618121048
1618121048929102200
暂停五秒
把时间戳再转变成年
2021-04-11 12:14:01 +0800 CST
时间相加
2021-04-12 14:04:08.9291022 +0800 CST m=+86400.003156501
定时器
2021-04-11 14:04:14.9676934 +0800 CST m=+6.041747701
2021-04-11 14:04:15.9563958 +0800 CST m=+7.030450101
2021-04-11 14:04:16.9524537 +0800 CST m=+8.026508001
2021-04-11 14:04:17.9617691 +0800 CST m=+9.035823401
2021-04-11 14:04:18.9694327 +0800 CST m=+10.043487001
2021-04-11 14:04:19.9576334 +0800 CST m=+11.031687701
2021-04-11 14:04:20.9564513 +0800 CST m=+12.030505601
2021-04-11 14:04:21.95758 +0800 CST m=+13.031634301
2021-04-11 14:04:22.9633547 +0800 CST m=+14.037409001
2021-04-11 14:04:23.9623826 +0800 CST m=+15.036436901


3.按照时区解析格式

package main

import (
	"fmt"
	"time"
)

func main() {
	loc, err := time.LoadLocation("Asia/Shanghai")
	if err != nil {
		fmt.Println("如果时间解析错误", err)
		return
	}
	fmt.Println(loc)
	t, err := time.ParseInLocation("2006-01-02 15:04:05", "2021-04-11 14:50:00", loc)
	if err != nil {
		fmt.Println("时间解析格式错误", err)
		return
	}
	fmt.Println(t)
}

 // 时间输出
 Asia/Shanghai
2021-04-11 14:50:00 +0800 CST



4.日志完整操作


4.1 日志文件的需求分析

  1. 往不同的地方输出日志

  2. 日志要分级别:

    • Debug
    • Trace
    • Info
    • Warning
    • Error
    • Fatal
  3. 日志要支持开关控制:能够在调试的过程中,输出debug,在其他的似乎,输出 error

  4. 完整的日记记录,应该包括 日志时间:文件夹的名字,日志级别,日志的信息。

  5. 日志文件要切割。

4.2 log自带的日志库

每过两秒打印一次日志记录

for {
		log.Println("这是一条日志")
		time.Sleep(2 * time.Second)
	}

// 输出
2021/04/11 15:05:48 这是一条日志
2021/04/11 15:05:50 这是一条日志
2021/04/11 15:05:52 这是一条日志
2021/04/11 15:05:54 这是一条日志
2021/04/11 15:05:56 这是一条日志

4.3 使用自带的日志库打印到文件里

package main

import (
	"fmt"
	"log"
	"os"
	"time"
)

func main() {
	// 先找到一个文件打开
	fileObj, err := os.OpenFile("./xx.log", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0)
	if err != nil {
		fmt.Println("打开文件失败", err)
		return
	}
	log.SetOutput(fileObj) // 把他写到打开的文件里
	for {
		log.Println("再试一下") // 此时不是打印到终端,而是打印到文件里
		time.Sleep(2 * time.Second)
	}
}

在这里插入图片描述


自己手写一个日记记录文件

package mylog

import (
	"errors"
	"fmt"
	"strings"
	"time"
)

type LogLevel uint32

const (
	DEBUG LogLevel = iota
	TRACE
	INFO
	WARNING
	UNKNOWN
)

// 往日记库里写东西

type Logger struct {
	level LogLevel
}

// 解析传入的函数
func parseLogLevel(s string) (LogLevel, error) { // 返回错误和logger
	// 先把传入的字符串导成大写
	s = strings.ToLower(s) // 全部都转成小写
	switch s {
	case "debug":
		return DEBUG, nil //
	case "trace":
		return TRACE, nil //
	case "warning":
		return WARNING, nil //
	default:
		err := errors.New("无效的日志级别")
		return UNKNOWN, err
	}

}

// 构造函数
func New(s string) *Logger {
	level, err := parseLogLevel(s)
	if err != nil {
		panic(err) // 用了 panic 就不用 return 了
	}
	return &Logger{
		level: level, // 把声明好好的 level 返回回去
	}
}

// 使用开关
func (l *Logger) enabled(loglevel LogLevel) bool {
	if l.level > loglevel {
		return true
	} else {
		return false
	}
}

// 打印看看

func (i *Logger) Debug(msg string) {
	if i.enabled(DEBUG) {
		// 打时间
		now := time.Now()
		fmt.Println("时间", now.Format("2006-01-02 T: 15:04:05"))
		// 打印信息
		fmt.Println(msg)
	}
}

func (i *Logger) TRACE(msg string) {
	row := time.Now()
	fmt.Println(msg, row)
}

func (i *Logger) Info(msg string) {
	fmt.Println(msg)
}

func (i *Logger) Warn(msg string) {
	fmt.Println(msg)
}

main 函数

package main

import (
	"fmt"
	"path"
	"runtime"

	"pengzhao.xyz/mylog"
)

func main() {
	fmt.Println("*****开始****")
	pc, file, line, ok := runtime.Caller(0) // 函数调用的堆栈信息,在main函数里调用,就要用0
	if !ok {
		fmt.Println("打开文件有问题")
	}

	fmt.Println(file) // 文件名
	// 拿到最下面的一层
	fmt.Println(path.Base(file)) // 只把最后一层的文件名拿出来

	fmt.Println(line) // 第几行

	// 拿到文件名
	funcName := runtime.FuncForPC(pc).Name() // 函数名
	fmt.Println(funcName)
	log := mylog.New("debug")
	log.Debug("有点小错误")
}

// 输出
*****开始****
D:/GoCode/src/pengzhao.xyz/test.go
test.go
13
main.main



字符串和其他格式之间的转换

func main() {
	i := "25"

	// 把字符串解析成int
	m, err := strconv.ParseInt(i, 10, 64) // 解析成10进制,64位
	if err != nil {
		fmt.Println(err)
		return
	}

	// 把字符串解析层 float 类型
	f1 := "25.8"
	c, _:= strconv.ParseFloat(f1, 10)
	fmt.Println(c)

	// 把字符串解析成 bool
	b1 := "true"
	b, _ := strconv.ParseBool(b1)
	fmt.Println(b)

	fmt.Printf("%d,%T", m, m)
	fmt.Println(m)
}

posted @ 2021-04-11 22:47  沧海一声笑rush  阅读(206)  评论(0编辑  收藏  举报