• 使用 Go 写入文件


    在本教程中,我们将学习如何使用 Go 将数据写入文件。我们还将学习如何同时写入文件。

    本教程有以下部分

    • 将字符串写入文件
    • 将字节写入文件
    • 逐行将数据写入文件
    • 附加到文件
    • 同时写入文件

    由于 Playground 不支持文件操作,请在本地系统中运行本教程的所有程序。

    将字符串写入文件

    最常见的文件写入操作之一是将字符串写入文件。这很简单。它由以下步骤组成。

    1. 创建文件
    2. 将字符串写入文件

    让我们立即开始讨论代码。

    package main
    
    import (
    	"fmt"
    	"os"
    )
    
    func main() {
    	f, err := os.Create("test.txt")
    	if err != nil {
    		fmt.Println(err)
    		return
    	}
    	l, err := f.WriteString("Hello World")
    	if err != nil {
    		fmt.Println(err)
            f.Close()
    		return
    	}
    	fmt.Println(l, "bytes written successfully")
    	err = f.Close()
    	if err != nil {
    		fmt.Println(err)
    		return
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    上面程序第 9 行中的函数创建了一个名为 test.txt 的文件。如果具有该名称的文件已存在,则 create 函数将截断该文件。此函数返回 File 描述符。https://pkg.go.dev/os#File)。

    在第 14 行,我们使用 方法将字符串Hello World写入文件WriteString。此方法返回写入的字节数和错误(如果有)。

    最后,我们关闭第 1 行的文件。21.

    上面的程序会打印

    11 bytes written successfully
    
    • 1

    您可以找到在执行该程序的目录中创建的名为test.txt的文件。如果使用任何文本编辑器打开该文件,您可以发现它包含文本Hello World

    将字节写入文件

    将字节写入文件与将字符串写入文件非常相似。我们将使用 Write 方法将字节写入文件。以下程序将字节切片写入文件。

    package main
    
    import (
    	"fmt"
    	"os"
    )
    
    func main() {
    	f, err := os.Create("/home/naveen/bytes")
    	if err != nil {
    		fmt.Println(err)
    		return
    	}
    	d2 := []byte{104, 101, 108, 108, 111, 32, 98, 121, 116, 101, 115}
    	n2, err := f.Write(d2)
    	if err != nil {
    		fmt.Println(err)
            f.Close()
    		return
    	}
    	fmt.Println(n2, "bytes written successfully")
    	err = f.Close()
    	if err != nil {
    		fmt.Println(err)
    		return
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    在上面的程序中,在第 15 行中,我们使用 Write 方法将字节切片写入目录中命名的文件。您可以将此目录更改为其他目录。其余程序是不言自明的。该程序将打印并创建一个名为 .打开文件,您可以看到它包含文本

    逐行将字符串写入文件

    另一种常见的文件操作是需要将字符串逐行写入文件。在本节中,我们将编写一个程序来创建包含以下内容的文件。

    Welcome to the world of Go.
    Go is a compiled language.
    It is easy to learn Go.
    
    • 1
    • 2
    • 3

    让我们立即开始讨论代码。

    package main
    
    import (
    	"fmt"
    	"os"
    )
    
    func main() {
    	f, err := os.Create("lines")
    	if err != nil {
    		fmt.Println(err)
                    f.Close()
    		return
    	}
    	d := []string{"Welcome to the world of Go1.", "Go is a compiled language.", "It is easy to learn Go."}
    
    	for _, v := range d {
    		fmt.Fprintln(f, v)
            if err != nil {
    			fmt.Println(err)
    			return
    		}
    	}
    	err = f.Close()
    	if err != nil {
    		fmt.Println(err)
    		return
    	}
    	fmt.Println("file written successfully")
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    在上面程序的第 9 行中,我们创建了一个名为 lines 的新文件。在第 17 行中,我们使用 for range 循环遍历数组,并使用 Fprintln 函数将行写入文件。Fprintln 函数将 a 作为参数并附加一个新行,这正是我们想要的。运行此程序将打印,并在当前目录中创建一个文件。该文件的内容如下

    Welcome to the world of Go1.
    Go is a compiled language.
    It is easy to learn Go.
    
    • 1
    • 2
    • 3

    追加到文件

    在本节中,我们将在上一节中创建的文件后再附加一行。我们将在文件后面附加一行文件处理很容易

    文件必须以追加和只写模式打开。这些标志作为参数传递给 Open 函数。在追加模式下打开文件后,我们将新行添加到文件中。

    package main
    
    import (
    	"fmt"
    	"os"
    )
    
    func main() {
    	f, err := os.OpenFile("lines", os.O_APPEND|os.O_WRONLY, 0644)
    	if err != nil {
    		fmt.Println(err)
    		return
    	}
    	newLine := "File handling is easy."
    	_, err = fmt.Fprintln(f, newLine)
    	if err != nil {
    		fmt.Println(err)
                    f.Close()
    		return
    	}
    	err = f.Close()
    	if err != nil {
    		fmt.Println(err)
    		return
    	}
    	fmt.Println("file appended successfully")
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    在上面程序的第 9 行中,我们以追加和只写模式打开文件。文件打开成功后,我们在第 15 行的文件中添加一个新行。该程序将打印 .运行此程序后,文件的内容将是

    Welcome to the world of Go1.
    Go is a compiled language.
    It is easy to learn Go.
    File handling is easy.
    
    • 1
    • 2
    • 3
    • 4

    并发写入文件

    当多个goroutine同时写入文件时,我们最终会遇到竞争条件。因此,必须使用通道来协调对文件的并发写入。

    我们将编写一个创建 100 个 goroutine 的程序。每个 goroutine 都会同时生成一个随机数,总共生成一百个随机数。这些随机数将被写入文件中。我们将使用以下方法解决竞争条件问题。

    1. 创建一个用于读取和写入生成的随机数的通道。
    2. 创建 100 个生产者 goroutine。每个 goroutine 都会生成一个随机数,并将该随机数写入通道。
    3. 创建一个消费者 goroutine,将从通道读取数据并将生成的随机数写入文件。因此,我们只有一个 goroutine 同时写入文件,从而避免竞争条件
    4. 完成后关闭文件。

    让我们produce首先编写生成随机数的函数。

    func produce(data chan int, wg *sync.WaitGroup) {
    	n := rand.Intn(999)
    	data <- n
    	wg.Done()
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    上面的函数生成一个随机数并将其写入通道data,然后调用Done等待组以通知其任务已完成。

    现在让我们转到写入文件的函数。

    func consume(data chan int, done chan bool) {
    	f, err := os.Create("concurrent")
    	if err != nil {
    		fmt.Println(err)
    		return
    	}
    	for d := range data {
    		_, err = fmt.Fprintln(f, d)
    		if err != nil {
    			fmt.Println(err)
    			f.Close()
    			done <- false
    			return
    		}
    	}
    	err = f.Close()
    	if err != nil {
    		fmt.Println(err)
    		done <- false
    		return
    	}
    	done <- true
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    consume函数创建一个名为concurrent. 然后它从通道读取随机数data并写入文件。一旦它读取并写入了所有随机数,它就会写入true通道done以通知它已完成其任务。

    让我们编写main函数并完成这个程序。我在下面提供了整个程序。

    package main
    
    import (
    	"fmt"
    	"math/rand"
    	"os"
    	"sync"
    )
    
    func produce(data chan int, wg *sync.WaitGroup) {
    	n := rand.Intn(999)
    	data <- n
    	wg.Done()
    }
    
    func consume(data chan int, done chan bool) {
    	f, err := os.Create("concurrent")
    	if err != nil {
    		fmt.Println(err)
    		return
    	}
    	for d := range data {
    		_, err = fmt.Fprintln(f, d)
    		if err != nil {
    			fmt.Println(err)
    			f.Close()
    			done <- false
    			return
    		}
    	}
    	err = f.Close()
    	if err != nil {
    		fmt.Println(err)
    		done <- false
    		return
    	}
    	done <- true
    }
    
    func main() {
    	data := make(chan int)
    	done := make(chan bool)
    	wg := sync.WaitGroup{}
    	for i := 0; i < 100; i++ {
    		wg.Add(1)
    		go produce(data, &wg)
    	}
    	go consume(data, done)
    	go func() {
    		wg.Wait()
    		close(data)
    	}()
    	d := <-done
    	if d {
    		fmt.Println("File written successfully")
    	} else {
    		fmt.Println("File writing failed")
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    main 函数在第 41 行创建通道,从中读取和写入随机数。第 42 行中的通道被 goroutine 用来通知它已完成其任务。第 43 行中的等待组用于等待所有 100 个 goroutines 完成随机数的生成。

    第 44 行中的循环创建了 100 个 goroutine。第 49 行中的 goroutine 调用要求等待组等待所有 100 个 goroutine 完成创建随机数。之后,它关闭通道。一旦通道关闭并且 goroutine 将所有生成的随机数写入文件,它就会写入第 37 行中的通道,并且主 goroutine 被解锁并打印。

    现在您可以在任何文本编辑器中并发打开文件并查看生成的 100 个随机数:)

    本教程到此结束。希望您喜欢阅读。祝你有美好的一天。

  • 相关阅读:
    FPGA片内RAM读写测试实验
    Python入坑系列-pyside6桌面编程之认识并设置理想字体效果
    CSS实现白天/夜晚模式切换
    SpringCloudAlibaba组件 — — OpenFeign的其他作用【超时时间、日志打印】
    羊城杯2022 部分web
    传统过程自动化工厂的智能扩展
    自动化测试练手项目推荐
    linux 设置登录失败次数限制
    openradar中最后跟踪的解释
    Microsoft Releases .NET 7新功能
  • 原文地址:https://blog.csdn.net/qq497811258/article/details/134245254