翻译:Go写文件

第36章 写文件

欢迎来到Golang系列教程的第36章。git

在这一章咱们将学习如何使用GO语言将数据写到文件里面。 而且还要学习如何同步的写到文件里面。github

这章教程包括以下几个部分:golang

将string写入文件
    将bytes写入文件
    将数据一行一行的写入文件
    追加到文件里
    同步写文件

请在本地运行全部本教程的程序,由于playground对文件的操做支持的并很差。数组

将string写入文件

最多见的写文件就是将string写入文件。 这个写起来很是的简单。 这个包涵如下几个阶段。app

建立文件
    将string写入文件

咱们将获得以下代码。编辑器

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
    }
}

在第9行使用create建立一个名字为test.txt的文件.若是这个文件已经存在,那么create方法将截断这个文件.方法返回文件的句柄.学习

在第14行,咱们使用WriteString将字符串Hello World写入到文件里面. 这个方法将返回相应写入的字节个数,若是有错误则返回错误.code

在第21行的时候将文件关闭.blog

上面程序的运行结果以下:教程

11 bytes written successfully

运行完成以后你会在程序运行的目录下发现建立了一个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, 119, 111, 114, 108, 100}
    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
    }
}

在上面的程序中,第15行使用了Write方法将字符切片写入到bytes这个文件里. 这个文本在目录/home/naveen目录里面. 你也能够将这个目录换成其余的目录.剩余的程序自带解释. 若是执行成功,这个程序将打印11 bytes written successfully.而且建立一个bytes的文件.打开文件,你会发现该文件包含了hello的字节.

将字符串一行一行的写入文件

另一个经常使用的操做就是将字符串一行一行的写入到文件.这一部分咱们将写一个程序,该程序建立并写入以下内容到文件里.

Welcome to the world of Go.
Go is a compiled language.
It is easy to learn Go.

让咱们看下面的代码:

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")
}

在上面程序的第9行,咱们先建立一个名字叫作lines的文件. 在第17行,咱们用迭代并使用for rang循环这个数组, 并使用Fprintln这个方法写入一行到文件里. 方法Fprintln方法将io.writer作为参数,而且添加一个新的行, 这个正是咱们想要的. 若是执行成功将打印file written successfully, 而且在当前目录将建立一个lines的文件.lines这个文件的内容以下所示:

Welcome to the world of Go1.
Go is a compiled language.
It is easy to learn Go.

追加文件

这一部分咱们将追加一行到lines这个文件.咱们将追加File handling is easylines这个文件.

这个文件将以追加和写的方式打开. 这些标志将经过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")
}

在上面程序的第9行,咱们以写的方式打开文件并将一行添加到文件里. 当成功打开文件以后,在程序第15行,咱们添加一行到文件里. 程序成功将打印file appended successfully. 运行程序,新的行就加到文件里面去了.

Welcome to the world of Go1.
Go is a compiled language.
It is easy to learn Go.
File handling is easy.

同步写文件

当多个goroutines同时写文件时, 咱们须要使用同步锁解决. 当发生同步写的时候须要一个channel做为一致写入的条件.

咱们将写一个程序,该程序建立100个goroutinues. 每一个goroutinue将同时产生一个随机数,届时将有100个随机数产生. 这些随机数将被写入到文件里面. 咱们将用下面的方法解决这个问题.

建立一个channel用来读和写这个随机数.

建立100个用于生产的goroutine. 每一个goroutine将产生随机数并将随机数写入到channel里

建立一个用于消费的goroutine用来读取channel中的随机数. 这样的话咱们就只有一个goroutinue向文件中写数据,从而避免竞争的关系.

关闭文件.

咱们开始写产生随机数的方法:

func produce(data chan int, wg *sync.WaitGroup) {
    n := rand.Intn(999)
    data <- n
    wg.Done()
}

上面的方法产生随机数而且将数据写入到channel中. 当完成以后经过waitGroup通知其任务已经完成.

让咱们看看将数据写到文件的方法:

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
}

这个consume的方法建立了一个concurrent的文件. 而后从channel中读取写入的随机数而且写到文件中. 一旦读取完成而且将随机数写入文件后,将在done这个channel中写入true,而后通知其任务完成.

下面咱们写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 == true {
        fmt.Println("File written successfully")
    } else {
        fmt.Println("File writing failed")
    }
}

main方法在第41行建立建立写入和读取数据的channel, 在第42行建立done这个channel, 此channel用于消费者goroutinue完成任务以后通知main方法.第43行建立Waitgroup的实例wg, 用于等待全部生产随机数的goroutine完成任务.

在第44行使用for循环建立100个goroutines. 在第49行调用waitgroup的wait()方法等待全部的goroutines完成随机数的生成. 而后关闭channel. 当channel关闭时,消费者的goroutine已经将全部的随机数写入文件,在第37行 的done channel中写入true. 这个时候main方法解除阻塞而且打印File written successfully.

这个时候你能够用任何的文本编辑器打开文件,能够看到100个随机数已经写入.

至此这篇教程就结束了,但愿你喜欢,祝你有美好的一天!


via: https://blog.golang.org/using-go-modules

做者:Naveen Ramanathan 译者:amei 校对:校对者ID

本文由 GCTT 原创编译, Go 中文网 荣誉推出

相关文章
相关标签/搜索