目 录CONTENT

文章目录

Golang IO 编程

Sakura
2023-11-25 / 0 评论 / 0 点赞 / 21 阅读 / 7814 字 / 正在检测是否收录...

Golang IO 编程

1. JSON 序列化

序列化就是把比变量转为二进制流 ( 二进制流可以跟[]byte 等价,[]byte 又可以跟 string 等价 )

序列化的目的是为了写入磁盘或者发送到网络上

type User struct {
	ID       int       // 默认的JSON字段名和原始变量名一致
	Name     string    `json:"name"` // 自定义JSON字段名
	age      int       // 不可导出的成员变量不会被序列化(不会被导出到磁盘或者网络)
	Birthday time.Time // 2023-11-25 23:10:52.3471691 +0800 CST m=+0.003135501
	CreatedAt MyDate // 自定义结构体
}

标准库使用反射进行 JSON 序列化,通过反射可以在运行时动态的获得结构器成员变量的名称,( JSON ),是否可以导出,可以获取成员变量,还可以调用结构体的方法(比如MarshalJSON和 UnmarhshalJSON)

2. 并行处理文件

  1. 首先统计路径下的所有文件和目录

// 统计一个路径下有个几个文件或者目录
func CountDirAndFile(dir string) error {
	Files := make([]string, 0, 10)
	Dirs := make([]string, 0, 10)

	// WalkDir内部会递归遍历目录
	// fs.DirEntry 代表一个目录项,包含了文件名、文件类型、文件权限等信息
	filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
		if err != nil {
			log.Fatal(err)
		}
		// 通过fs.DirEntry.Info()获取文件信息
		info, err := d.Info()
		if err != nil {
			log.Fatal(err)
		}
		// IsRegular()判断是否是文件
		// IsDir()判断是否是目录
		if info.Mode().IsRegular() {
			Files = append(Files, path)
		} else if info.Mode().IsDir() {
			// 因为路径也会被当成目录,所以不应该在Dir中增加传入的路径
			if path == dir {

			} else {
				Dirs = append(Dirs, path)
			}
		}

		return nil
	})
	fmt.Println("路径", dir, "下面有", len(Files), "个文件, ", len(Dirs), "个目录")
	fmt.Println(Files)
	fmt.Println(Dirs)
	return Files
}

3. 并行写入文件

  • 打开文件后通过 goroutine 并发的写入内容

var Content = "Sakura 2023-11-26\n"

// 并发写入文件
// os.File支持并发调用
func FileWrite(goroutine int, file *os.File) {
	wg := sync.WaitGroup{}
	wg.Add(goroutine)
	for i := 0; i < goroutine; i++ {
		go func() {
			defer wg.Done()
			for j := 0; j < 10000; j++ {
				if _, err := file.WriteString(Content); err != nil {
					panic(err)
				}
			}
		}()
	}
	wg.Wait()
}
  • 测试

func TestFileRead(t *testing.T) {
	path := "data/2.txt"
	file, err := os.OpenFile(path, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0666)
	if err != nil {
		fmt.Println(err)
	}
	for i := 0; i < 100000; i++ {
		file.WriteString("Sakura 2023 \n")
	}
}

  • 串行写文件

func TestFileRead(t *testing.T) {
	path := "data/2.txt"
	file, err := os.OpenFile(path, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0666)
	if err != nil {
		fmt.Println(err)
	}
	for i := 0; i < 100000; i++ {
		file.WriteString("Sakura 2023-11-26\n")
	}
}

可以看到并发写文件是没有串行写文件快的

  • 并发写文件的使用场景:一个并发执行的接口下调用写日志

5. 并行读文件

6. 压缩和解压

Golang 标准库 compress 包下实现了 bzip2 , DEFLATE , gzip , lzw 和 zlib 压缩算法

  • 压缩

// 使用Gzip压缩
func GzipCompress(InFile, OutFile string) {
		// 打开要压缩的文件

	SourceFile, err := os.Open(InFile)
	if err != nil {
		log.Fatal(err)
	}
	defer SourceFile.Close()
	// 统计文件信息
	fileInfo, _ := SourceFile.Stat()
	fmt.Println("压缩前的文件大小为:", fileInfo.Size())

	// 创建压缩后的文件
	DestFile, err := os.OpenFile(OutFile, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
	if err != nil {
		log.Fatal(err)
	}
	defer DestFile.Close()

	// 1.创建gzipwriter
	gzipWriter := gzip.NewWriter(DestFile)
	defer gzipWriter.Close()

	// 把一个流复制到另一个流中
	io.Copy(gzipWriter, SourceFile)
	//
	//gzipWriter.Close()
	//DestFile.Close()
	//SourceFile.Close()
}
  • 单元测试

func TestGzipCompress(t *testing.T) {
	// 定义要压缩的文件和解压后的文件
	SourceFile := "Sakura.txt"
	DestFile := "Sakura.txt.gzip"
	// 调用压缩函数
	GzipCompress(SourceFile, DestFile)
	//// 调用解压函数
	//GzipUnCompress(DestFile, "Sakura.txt")
}
  • 解压

// 解压
func GzipDeCompress(InFile, OutFile string) {
	// 打开解压的文件
	SourceFile, err := os.Open(InFile)
	if err != nil {
		log.Fatal(err)
	}
	defer SourceFile.Close()
	stat, err := SourceFile.Stat()
	fmt.Println(stat.Name(), "的大小为:", stat.Size(), "B")

	// 创建解压后的文件
	DestFile, err := os.OpenFile(OutFile, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
	if err != nil {
		log.Fatal(err)
	}
	defer DestFile.Close()

	// 2.创建gzipreader
	gzipReader, err := gzip.NewReader(SourceFile)
	if err != nil {
		log.Fatal(gin.Default())
	}
	defer gzipReader.Close()

	io.Copy(DestFile, gzipReader)

}
  • 单元测试

func TestGzipCompress(t *testing.T) {
	// 定义要压缩的文件和解压后的文件
	SourceFile := "Sakura.txt"
	DestFile := "Sakura.txt.gzip"
	// 调用压缩函数
	GzipCompress(SourceFile, DestFile)
	// 调用解压函数
	GzipDeCompress(DestFile, "Sakura_DeCompress.txt")
}

  • 压缩的文件和解压后的文件

0

评论区