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


      目录
      相关文章
      |
      18天前
      |
      Go 数据库
      Go语言中的包(package)是如何组织的?
      在Go语言中,包是代码组织和管理的基本单元,用于集合相关函数、类型和变量,便于复用和维护。包通过目录结构、文件命名、初始化函数(`init`)及导出规则来管理命名空间和依赖关系。合理的包组织能提高代码的可读性、可维护性和可复用性,减少耦合度。例如,`stringutils`包提供字符串处理函数,主程序导入使用这些函数,使代码结构清晰易懂。
      63 11
      |
      2月前
      |
      Linux Go iOS开发
      怎么禁用 vscode 中点击 go 包名时自动打开浏览器跳转到 pkg.go.dev
      本文介绍了如何在 VSCode 中禁用点击 Go 包名时自动打开浏览器跳转到 pkg.go.dev 的功能。通过将 gopls 的 `ui.navigation.importShortcut` 设置为 &quot;Definition&quot;,可以实现仅跳转到定义处而不打开链接。具体操作步骤包括:打开设置、搜索 gopls、编辑 settings.json 文件并保存更改,最后重启 VSCode 使设置生效。
      67 7
      怎么禁用 vscode 中点击 go 包名时自动打开浏览器跳转到 pkg.go.dev
      |
      3月前
      |
      Go 索引
      go语言使用strings包
      go语言使用strings包
      47 3
      |
      3月前
      |
      存储 负载均衡 监控
      如何利用Go语言的高效性、并发支持、简洁性和跨平台性等优势,通过合理设计架构、实现负载均衡、构建容错机制、建立监控体系、优化数据存储及实施服务治理等步骤,打造稳定可靠的服务架构。
      在数字化时代,构建高可靠性服务架构至关重要。本文探讨了如何利用Go语言的高效性、并发支持、简洁性和跨平台性等优势,通过合理设计架构、实现负载均衡、构建容错机制、建立监控体系、优化数据存储及实施服务治理等步骤,打造稳定可靠的服务架构。
      66 1
      |
      3月前
      |
      JSON 安全 Go
      Go语言中使用JWT鉴权、Token刷新完整示例,拿去直接用!
      本文介绍了如何在 Go 语言中使用 Gin 框架实现 JWT 用户认证和安全保护。JWT(JSON Web Token)是一种轻量、高效的认证与授权解决方案,特别适合微服务架构。文章详细讲解了 JWT 的基本概念、结构以及如何在 Gin 中生成、解析和刷新 JWT。通过示例代码,展示了如何在实际项目中应用 JWT,确保用户身份验证和数据安全。完整代码可在 GitHub 仓库中查看。
      455 1
      |
      3月前
      |
      Go 调度 开发者
      探索Go语言中的并发模式:goroutine与channel
      在本文中,我们将深入探讨Go语言中的核心并发特性——goroutine和channel。不同于传统的并发模型,Go语言的并发机制以其简洁性和高效性著称。本文将通过实际代码示例,展示如何利用goroutine实现轻量级的并发执行,以及如何通过channel安全地在goroutine之间传递数据。摘要部分将概述这些概念,并提示读者本文将提供哪些具体的技术洞见。
      |
      3月前
      |
      编译器 Go 开发者
      go语言中导入相关包
      【11月更文挑战第1天】
      41 3
      |
      3月前
      |
      Unix Linux Go
      go进阶编程:Golang中的文件与文件夹操作指南
      本文详细介绍了Golang中文件与文件夹的基本操作,包括读取、写入、创建、删除和遍历等。通过示例代码展示了如何使用`os`和`io/ioutil`包进行文件操作,并强调了错误处理、权限控制和路径问题的重要性。适合初学者和有经验的开发者参考。
      |
      3月前
      |
      算法 大数据 Go
      Go文件操作:掌握Go的文件读写与操作技巧
      本文介绍了Go语言的文件操作功能,包括文件的打开、读写和关闭。Go语言通过`os`和`io`包提供了丰富的文件操作接口,使开发者能够轻松实现文件的读写和管理。文章详细讲解了核心概念、具体操作步骤和代码示例,并探讨了实际应用场景和未来发展趋势。
      |
      3月前
      |
      存储 前端开发 Go
      Go 文件的读取操作
      本文介绍了 Go 语言标准库中的 `os` 包和 `bufio` 包,重点讲解了 `os` 包中的 `Open` 和 `OpenFile` 函数及 `File` 结构体的 `Read` 方法,以及 `bufio` 包中的 `NewReader` 函数和 `Reader` 结构体的 `ReadString` 方法。通过示例代码展示了如何使用这些方法高效读取文件,减少磁盘操作。