GO 利用bufio包(流式操作) - 并发写文件/读文件示例

简介: GO 利用bufio包(流式操作) - 并发写文件/读文件示例

 并发写文件:

注意点:

    • runtime.GOMAXPROCS(runtime.NumCPU()) 限制并发写操作的协程数:

    协程数不宜过多,避免协程间的频繁切换影响性能(根据cpu核数而定)

    • WriteString()操作要加锁,否则最终写入数据有问题(乱码等...)
    • 最后记得Flush()一下:

    bufio 通过 flush 操作将缓冲写入真实的文件的,所以一定要在关闭文件之前先flush,否则会造成数据丢失的情况

    packagemainimport (
    "bufio""fmt""os""runtime""runtime/debug""sync")
    // bufio库的流式处理  如果文件较小,使用ioutil也不失为一种方法funcWriteDataToTxt() {
    txtFile, err :=os.OpenFile("55555.txt", os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777) // O_TRUNC 清空重写iferr!=nil {
    fmt.Println("WriteDataToTxt os.OpenFile() err:", err)
    return    }
    defertxtFile.Close()
    // txtFile.WriteString() // os操作文件-效率低bufWriter :=bufio.NewWriter(txtFile)
    varwgsync.WaitGrouplimitChan :=make(chanstruct{}, runtime.GOMAXPROCS(runtime.NumCPU())) // 最大并发协程数varmutexsync.Mutexfori :=0; i<10000; i++ { // 写1w行测试limitChan<-struct{}{}
    wg.Add(1)
    gofunc(jint) {
    deferfunc() {
    ife :=recover(); e!=nil {
    fmt.Printf("WriteDataToTxt panic: %v,stack: %s\n", e, debug.Stack())
    // return                }
    wg.Done()
    <-limitChan            }()
    // 模拟业务逻辑:先整合所有数据,然后再统一写WriteString()strId :=fmt.Sprintf("%v", j)
    strName :=fmt.Sprintf(" user_%v", j)
    strScore :=fmt.Sprintf(" %d", j*10)
    mutex.Lock() // 要加锁/解锁,否则 bufWriter.WriteString 写入数据有问题_, err :=bufWriter.WriteString(strId+strName+strScore+"\n")
    iferr!=nil {
    fmt.Printf("WriteDataToTxt WriteString err: %v\n", err)
    return            }
    mutex.Unlock()
    // bufWriter.Flush() // 刷入磁盘(错误示例:WriteDataToTxt err: short write,short write;因为循环太快,有时写入的数据量太小了)        }(i)
        }
    wg.Wait()
    bufWriter.Flush() // 刷入磁盘(正确示例,bufio 通过 flush 操作将缓冲写入真实的文件的,所以一定要在关闭文件之前先flush,否则会造成数据丢失的情况)}

    image.gif

    报错:

    image.gif编辑

    读文件:

    注意点:

      • 读取文件中一行内容时,ReadSliceReadLine性能优于ReadBytesReadString,但由于ReadLine对换行的处理更加全面(兼容\n\r\n换行),因此,实际开发过程中,建议使用ReadLine函数。
      • 关于os.File、bufio、ioutil 写文件的性能比较,参考:
        https://segmentfault.com/a/1190000023691973
      packagemainimport (
      "bufio""fmt""io""os")
      // 读文件funcReadDataFromTxt() {
      txtFile, err :=os.OpenFile("55555.txt", os.O_RDONLY, 0777) // O_TRUNC 清空重写iferr!=nil {
      fmt.Println("WriteDataToTxt os.OpenFile() err:", err)
      return    }
      defertxtFile.Close()
      bufReader :=bufio.NewReader(txtFile)
      for {
      data, _, err :=bufReader.ReadLine() // 读一行日志iferr==io.EOF {                   // 如果列表读完了,退出fmt.Println("数据读完了~")
      break        }
      fmt.Println("data: ", string(data))
          }
      return}

      image.gif


      目录
      相关文章
      |
      1天前
      |
      Java 大数据 Go
      Go语言:高效并发的编程新星
      【10月更文挑战第21】Go语言:高效并发的编程新星
      14 7
      |
      6天前
      |
      安全 Go 调度
      探索Go语言的并发模式:协程与通道的协同作用
      Go语言以其并发能力闻名于世,而协程(goroutine)和通道(channel)是实现并发的两大利器。本文将深入了解Go语言中协程的轻量级特性,探讨如何利用通道进行协程间的安全通信,并通过实际案例演示如何将这两者结合起来,构建高效且可靠的并发系统。
      |
      6天前
      |
      安全 Go 开发者
      破译Go语言中的并发模式:从入门到精通
      在这篇技术性文章中,我们将跳过常规的摘要模式,直接带你进入Go语言的并发世界。你将不会看到枯燥的介绍,而是一段代码的旅程,从Go的并发基础构建块(goroutine和channel)开始,到高级模式的实践应用,我们共同探索如何高效地使用Go来处理并发任务。准备好,让Go带你飞。
      |
      7天前
      |
      安全 Go 调度
      探索Go语言的并发之美:goroutine与channel
      在这个快节奏的技术时代,Go语言以其简洁的语法和强大的并发能力脱颖而出。本文将带你深入Go语言的并发机制,探索goroutine的轻量级特性和channel的同步通信能力,让你在高并发场景下也能游刃有余。
      |
      19天前
      |
      存储 Go 文件存储
      M.2移动硬盘打造Win To Go系统:高效分区存储文件全攻略
      【10月更文挑战第12天】本文详细介绍了如何使用M.2移动硬盘制作Win To Go系统。首先,需准备合适容量与接口类型的M.2硬盘及硬盘盒,并获取Windows镜像文件和分区工具。接着,通过Rufus软件将镜像写入硬盘。文中还提供了分区策略,包括系统分区(约80-120GB)、软件分区(根据需求设定)和数据分区(剩余空间),并指导如何使用DiskGenius或Windows自带工具进行分区。最后,强调了对各分区文件的有效管理和定期备份的重要性。
      |
      20天前
      |
      存储 固态存储 Go
      M.2移动硬盘打造Win To Go系统:高效分区存储文件全攻略
      【10月更文挑战第11天】Win To Go 是一种将 Windows 系统安装在 M.2 移动硬盘上的技术,便于用户携带自定义系统跨设备使用。需准备高性能 M.2 硬盘及合适硬盘盒,并使用 DiskGenius 或 Rufus 进行分区与系统安装。系统分区用于安装 Windows,其余分区可根据需求存储工作或娱乐文件,便于管理和备份。
      |
      4天前
      |
      安全 程序员 Go
      深入浅出Go语言的并发之道
      在本文中,我们将探索Go语言如何优雅地处理并发编程。通过对比传统多线程模型,我们将揭示Go语言独特的goroutine和channel机制是如何简化并发编程,并提高程序的效率和稳定性。本文不涉及复杂的技术术语,而是用通俗易懂的语言,结合生动的比喻,让读者能够轻松理解Go语言并发编程的核心概念。
      |
      2月前
      |
      存储 安全 Go
      Go to Learn Go之并发
      Go to Learn Go之并发
      28 8
      |
      9天前
      |
      存储 Go 数据库
      Go语言Context包源码学习
      【10月更文挑战第21天】Go 语言中的 `context` 包用于在函数调用链中传递请求上下文信息,支持请求的取消、超时和截止时间管理。其核心接口 `Context` 定义了 `Deadline`、`Done`、`Err` 和 `Value` 方法,分别用于处理截止时间、取消信号、错误信息和键值对数据。包内提供了 `emptyCtx`、`cancelCtx`、`timerCtx` 和 `valueCtx` 四种实现类型,满足不同场景需求。示例代码展示了如何使用带有超时功能的上下文进行任务管理和取消。
      |
      16天前
      |
      安全 Go 调度
      探索Go语言的并发之美:goroutine与channel的实践指南
      在本文中,我们将深入探讨Go语言的并发机制,特别是goroutine和channel的使用。通过实际的代码示例,我们将展示如何利用这些工具来构建高效、可扩展的并发程序。我们将讨论goroutine的轻量级特性,channel的同步通信能力,以及它们如何共同简化并发编程的复杂性。