翻譯: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 中文網 榮譽推出

相關文章
相關標籤/搜索