Escribir ficheros es una de las operaciones mas comunes en Go, en este artículo aprenderemos las distintas posibilidades que nos ofrece para hacerlo.
El artículo se compone de varias secciones:
- Escribir un string.
- Escribir bytes.
- Escribir línea a línea.
- Añadir contenido.
- Escrituras concurrentes
Si eres nuevo en el mundo de Go te recomiendo los siguientes artículos anteriores:
- Go basics
- Go functions
- Go unit tests
- Go pointers
- Go interfaces
- Go structs
- Go generics
- Go errors
- Go routines
- Go strings, chars y runas
- Go defer
- Go first class functions
- Go reflection
- Go reading files
Escribir un string:
El código es bastante auto explicativo.
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\n")
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
}
}
12 bytes written successfully
cat test.txt
Hello World
Escribir bytes:
Escribir una secuencia de bytes es muy similar al ejemplo anterior, tan solo debemos crear el slice de bytes y escribirlos.
package main
import (
"fmt"
"os"
)
func main() {
f, err := os.Create("test.txt")
if err != nil {
fmt.Println(err)
return
}
d2 := []byte{72, 101, 108, 108, 111, 32, 66, 121, 116, 101, 115, 10}
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
}
}
12 bytes written successfully
cat test.txt
Hello Bytes
Escribir línea a línea:
Para escribir por líneas vamos a crear un slice con cada una de las líneas y las escribiremos mediante la función fmt.Fprintln() que recibe como primer parámetro de entrada el descriptor del fichero a escribir y como segundo parámetro la línea a escribir.
package main
import (
"fmt"
"os"
)
func main() {
f, err := os.Create("test.txt")
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")
}
File written successfully
cat test.txt
Welcome to the world of Go1.
Go is a compiled language.
It is easy to learn Go.
Añadir contenido:
Para añadir contenido a un fichero previamente existente no debemos utilizar la función os.Create(), si no os.OpenFile().
Debemos indicar el fichero, el modo de acceso y los permisos. Estos serán utilizados en caso de que el fichero no exista y se haya especificado el modo O_CREATE, si existe previamente se dejan los permisos existentes. Incluso cuando no se utiliza el modo O_CREATE como es el caso, la función nos fuerza a indicar unos permisos.
package main
import (
"fmt"
"os"
)
func main() {
f, err := os.OpenFile("test.txt", 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")
}
File appended successfully
cat test.txt
Already existent line
File handling is easy.
Escrituras concurrentes:
Escribir en paralelo es tan sencillo como llamar a la función encargada de escribir mediante go routines , tan solo debemos tener en cuenta que hay que utilizar un waitGroup para controlar cuando han acabado todas ellas de escribir.
package main
import (
"fmt"
"os"
"strconv"
"sync"
)
func writeLine(f *os.File, newLine string, wg *sync.WaitGroup) {
_, err := fmt.Fprintln(f, newLine)
wg.Done()
if err != nil {
fmt.Println(err)
}
}
func main() {
f, err := os.OpenFile("test.txt", os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
fmt.Println(err)
return
}
wg := sync.WaitGroup{}
for i := 1; i <= 300; i++ {
newLine := "Line: " + strconv.Itoa(i)
wg.Add(1)
go writeLine(f, newLine, &wg)
}
wg.Wait()
err = f.Close()
if err != nil {
fmt.Println(err)
return
}
fmt.Println("File appended successfully")
}
File appended successfully
wc -l test.txt
300 test.txt