Golang input/output: Difference between revisions

From wikinotes
 
(37 intermediate revisions by the same user not shown)
Line 1: Line 1:
Sending/Receiving and Writing/Reading.<br>
You may also be interested in [[golang filesystem]].
= Documentation =
= Documentation =
<blockquote>
<blockquote>
Line 5: Line 8:
| <code>fmt</code> || https://pkg.go.dev/fmt@go1.18.2
| <code>fmt</code> || https://pkg.go.dev/fmt@go1.18.2
|-
|-
| <code>io/ioutil</code> (read/write) || https://pkg.go.dev/io/ioutil@go1.18.3
| <code>os</code> (open files) || https://pkg.go.dev/os@go1.18.3
|-
|-
| <code>io/fs</code> (filesystem) || https://pkg.go.dev/io/fs@go1.18.3
| <code>bufio.Reader</code> || https://pkg.go.dev/bufio@go1.18.3#Reader
|-
| <code>bufio.Writer</code> || https://pkg.go.dev/bufio@go1.18.3#Writer
|-
|-
| <code>textproto</code> (sockets) || https://pkg.go.dev/net/textproto@go1.18.3
| <code>textproto</code> (sockets) || https://pkg.go.dev/net/textproto@go1.18.3
Line 14: Line 19:
</blockquote><!-- Documentation -->
</blockquote><!-- Documentation -->


= print =
= Stdin, Stdout, Stderr =
<blockquote>
== Basics ==
<blockquote>
<blockquote>
<syntaxhighlight lang="go">
<syntaxhighlight lang="go">
require "fmt"
fmt.Fprintln(os.Stdout, "writes stdout")
 
fmt.Fprintln(os.Stderr, "writes stderr")
fmt.Println("foo")                // print to stdout with newline
fmt.Printf("%v", 123)              // print formatted string to stdout (no newline)
fmt.Fprintf(os.Stdout, "%v", 123)  // prints formatted string to writable object (ex. STDOUT, STERR, ..)
 
fmt.Sprintf("%v", 123)            // returns formatted string (no newline)
</syntaxhighlight>
</syntaxhighlight>
</blockquote><!-- Basics -->
</blockquote><!-- stdin, stdout, stderr -->


== Format Syntax ==
= Reader, Writer Interfaces =
<blockquote>
<blockquote>
Printf/Sprintf/Fprintf all take format specifiers.<br>
The <code>bufio.Reader</code>, <code>bufio.Writer</code> interfaces described under the File header are general purpose.
See full docs [https://pkg.go.dev/fmt@go1.18.2 here], but here's some really useful formats:
Several types of objects may abstract their access using this interface.


<syntaxhighlight lang="bash">
<syntaxhighlight lang="go">
# general
// reader
%v  # value
strings.NewReader("abc\ndef") // strings
%T  # type
os.Open("file.txt")            // file
 
os.OpenFile("file.txt",        // file
# number-bases
            os.o_RDWR|os.O_APPEND,
%b  # binary
            0644)
%x  # hex
%o  # octal
%d  # decimal
 
# number types
%i  # int
%f  # float


# strings
// writer
%s  # string
writer := new(strings.Builder) // strings
%q  # quoted/escaped go string
os.Create("file.txt")          // file
%c  # unicode-char for num
os.OpenFile("file.txt",        // file
            os.o_RDWR|os.O_APPEND,
            0644)
</syntaxhighlight>
</syntaxhighlight>
</blockquote><!-- printf -->
</blockquote><!-- Reader, Writer -->
</blockquote><!-- print -->


= stdin, stdout, stderr =
= Files =
<blockquote>
<blockquote>
<syntaxhighlight lang="go">
If the files are small, you can work with them using <code>os</code>
fmt.Fprintln(os.Stdout, "writes stdout")
fmt.Fprintln(os.Stderr, "writes stderr")
</syntaxhighlight>
</blockquote><!-- stdin, stdout, stderr -->


= Filesystem =
== Reading ==
<blockquote>
== Errors ==
<blockquote>
<blockquote>
Small Files
<syntaxhighlight lang="go">
<syntaxhighlight lang="go">
require "errors"
import "os"
require "os"
require "io/fs"


_, err := os.Stat("foo.bar")
// read entire file into []byte
if errors.Is(err, fs.ErrExist) {...}
conts, err := os.ReadFile("/var/tmp/foo.txt")
if errors.Is(err, fs.ErrNotExist) {...}
if errors.Is(err, fs.ErrPermission) {...}
if errors.Is(err, fs.ErrPermission) {...}
</syntaxhighlight>
</syntaxhighlight>


{{ expand
Buffered Reading
| The old method defines <code>Is${N}</code> functions to test for various <code>os</code> package errors.
|
 
<syntaxhighlight lang="go">
<syntaxhighlight lang="go">
require "os"
// create or open file for reading
 
fd, err := os.Open("/var/tmp/foo.txt")       // open for reading
// example filesystem operations that create errors
fd, err := os.OpenFile("/var/tmp/foo.txt",    // open, setting open-mode flags
info, err := os.Stat("foo.bar")
                      os.O_RDWR|os.O_APPEND,
fd, err := os.Create("/etc/foo")
                      0644)
defer fd.Close()


// example error checks
// read up to 5 bytes
if os.IsExist(err) {...}
buf := make([]byte, 5)
if os.IsNotExist(err) {...}
bytes_r, err := fd.Read(buf)
if os.IsPermission(err) {...}
</syntaxhighlight>
</syntaxhighlight>
}}
</blockquote><!-- Errors -->


== Common Operations ==
Auto-Buffered Reader
<blockquote>
<syntaxhighlight lang="go">
<syntaxhighlight lang="go">
import "os"
fd, err := os.OpenFile("/var/tmp/foo.txt",    // open, setting open-mode flags
import "errors"
                      os.O_RDWR|os.O_APPEND,
 
                      0644)
// check if file exists
defer fd.Close()
if _, err := os.Stat("/var/foo.txt"); errors.Is(err, fs.ErrNotExist) {
reader := bufio.NewReader(fd)
    fmt.Println("file does not exist!")
}


dir, err := os.Getwd()
bytes, err := reader.ReadBytes("\n")   // read all characters until first occurrence of '\n'
err := os.Chmod("foo.txt", 0644)
string, err := reader.ReadString("\n") // read all characters until first occurrence of '\n'
err := os.Chown("foo.txt", -1, -1)          // '-1' means do not change uid/gid
err := os.Chown("foo.txt", 1000, -1)       // set uid '1000' as owner
 
err := os.Link("/var/foo", "/var/bar")      // hardlink
err := os.Symlink("/var/foo", "/var/bar")  // symlink
err := os.Mkdir("/var/foo")                // create directory (non recursively)
err := os.MkdirAll("/var/foo/bar/baz")      // creates directory (recursively)
 
err := os.Remove("/var/tmp/foo.bar")
err := os.RemoveAll("/var/tmp/foo")
err := os.Rename("a", "b")
</syntaxhighlight>
</syntaxhighlight>


Temporary Directories
You may also find it useful to gradually fill a buffer to process large files
<syntaxhighlight lang="go">
<syntaxhighlight lang="go">
// creates tempdir,
// fill buffer to capacity, reading from reader
// '*' in filename is placement of random str
buf := make([]byte, 64)
// you must delete!
_, err := os.ReadFull(reader, buf)
path, err := os.MkdirTemp("/var/tmp", "cache-*")
switch {
defer os.RemoveAll(path)
    case errors.Is(err, os.EOF):
        // nothing to read (0 bytes)
    case errors.Is(err, os.ErrUnexpectedEOF):
        // end of file, before filling buffer
}
</syntaxhighlight>
</syntaxhighlight>
</blockquote><!-- Common Operations -->
</blockquote><!-- Reading -->


== Files ==
== Writing ==
<blockquote>
<blockquote>
Small Files
<syntaxhighlight lang="go">
<syntaxhighlight lang="go">
File.Create
import "os"
File.CreateTemp
File.NewFile
File.Open


File.Write
// replace file (creating if necessary)
File.WriteString
err := os.WriteFile("/var/tmp/foo.txt", []byte("abc"), 0644)
 
File.Stat
File.FileInfo
</syntaxhighlight>
</syntaxhighlight>
</blockquote><!-- Files -->


== Locations ==
Manually Buffered Writing
<blockquote>
<syntaxhighlight lang="go">
<syntaxhighlight lang="go">
// XDG spec
fd, err := os.Create(filepath)                // create, or truncate file (0666 perms)
dir, err := os.UserHomeDir()
fd, err := os.OpenFile("/var/tmp/foo.txt",    // open, setting open-mode flags
dir, err := os.UserConfigDir()
                      os.O_RDWR|os.O_APPEND,
dir, err := os.UserCacheDir()
                      0644)
defer fd.Close()
 
bytes_w, err := fd.Write([]byte("abc"))
bytes_w, err := fd.WriteString("abc")
 
fd.Sync() // sync writes to disk
</syntaxhighlight>
</syntaxhighlight>
</blockquote><!-- Locations -->


move me
Auto Buffered Writer
<syntaxhighlight lang="go">
<syntaxhighlight lang="go">
host, err := os.Hostname()
import "os"
</syntaxhighlight>
import "bufio"
</blockquote><!-- Filesystem -->


= Files =
fd, err := os.OpenFile("foo.txt", os.O_WRONLY|os.O_APPEND, 0644)
<blockquote>
defer fd.Close()
<syntaxhighlight lang="go">
require "os"


os.WriteFile("/var/tmp/foo.txt", []byte("abc"), 0644)
writer := bufio.NewWriter(fd)
bytes_w, err := writer.Write([]byte("abc"))
bytes_w, err := writer.WriteString("abc")


conts, err := os.ReadFile("/var/tmp/foo.txt")
writer.Flush(// ensure all writes written to disk before closing
</syntaxhighlight>
</syntaxhighlight>
</blockquote><!-- Writing -->
</blockquote><!-- Files -->
</blockquote><!-- Files -->


Line 195: Line 159:
conn, err = net.Dial("tcp", "10.10.10.10:6600")
conn, err = net.Dial("tcp", "10.10.10.10:6600")
defer conn.Close()
defer conn.Close()
</syntaxhighlight>


<syntaxhighlight lang="go">
// sending message to socket
// sending message to socket
_, err = conn.Write([]byte("search title 'it ceases to be'"))
_, err = conn.Write([]byte("search title 'it ceases to be'"))

Latest revision as of 00:59, 26 June 2022

Sending/Receiving and Writing/Reading.
You may also be interested in golang filesystem.

Documentation

fmt https://pkg.go.dev/fmt@go1.18.2
os (open files) https://pkg.go.dev/os@go1.18.3
bufio.Reader https://pkg.go.dev/bufio@go1.18.3#Reader
bufio.Writer https://pkg.go.dev/bufio@go1.18.3#Writer
textproto (sockets) https://pkg.go.dev/net/textproto@go1.18.3

Stdin, Stdout, Stderr

fmt.Fprintln(os.Stdout, "writes stdout")
fmt.Fprintln(os.Stderr, "writes stderr")

Reader, Writer Interfaces

The bufio.Reader, bufio.Writer interfaces described under the File header are general purpose. Several types of objects may abstract their access using this interface.

// reader
strings.NewReader("abc\ndef") // strings
os.Open("file.txt")            // file
os.OpenFile("file.txt",        // file
            os.o_RDWR|os.O_APPEND,
            0644)

// writer
writer := new(strings.Builder) // strings
os.Create("file.txt")           // file
os.OpenFile("file.txt",         // file
            os.o_RDWR|os.O_APPEND,
            0644)

Files

If the files are small, you can work with them using os

Reading

Small Files

import "os"

// read entire file into []byte
conts, err := os.ReadFile("/var/tmp/foo.txt")

Buffered Reading

// create or open file for reading
fd, err := os.Open("/var/tmp/foo.txt")        // open for reading
fd, err := os.OpenFile("/var/tmp/foo.txt",    // open, setting open-mode flags
                       os.O_RDWR|os.O_APPEND,
                       0644)
defer fd.Close()

// read up to 5 bytes
buf := make([]byte, 5)
bytes_r, err := fd.Read(buf)

Auto-Buffered Reader

fd, err := os.OpenFile("/var/tmp/foo.txt",    // open, setting open-mode flags
                       os.O_RDWR|os.O_APPEND,
                       0644)
defer fd.Close()
reader := bufio.NewReader(fd)

bytes, err := reader.ReadBytes("\n")   // read all characters until first occurrence of '\n'
string, err := reader.ReadString("\n") // read all characters until first occurrence of '\n'

You may also find it useful to gradually fill a buffer to process large files

// fill buffer to capacity, reading from reader
buf := make([]byte, 64)
_, err := os.ReadFull(reader, buf)
switch {
    case errors.Is(err, os.EOF):
        // nothing to read (0 bytes)
    case errors.Is(err, os.ErrUnexpectedEOF):
        // end of file, before filling buffer
}

Writing

Small Files

import "os"

// replace file (creating if necessary)
err := os.WriteFile("/var/tmp/foo.txt", []byte("abc"), 0644)

Manually Buffered Writing

fd, err := os.Create(filepath)                 // create, or truncate file (0666 perms)
fd, err := os.OpenFile("/var/tmp/foo.txt",    // open, setting open-mode flags
                       os.O_RDWR|os.O_APPEND,
                       0644)
defer fd.Close()

bytes_w, err := fd.Write([]byte("abc"))
bytes_w, err := fd.WriteString("abc")

fd.Sync()  // sync writes to disk

Auto Buffered Writer

import "os"
import "bufio"

fd, err := os.OpenFile("foo.txt", os.O_WRONLY|os.O_APPEND, 0644)
defer fd.Close()

writer := bufio.NewWriter(fd)
bytes_w, err := writer.Write([]byte("abc"))
bytes_w, err := writer.WriteString("abc")

writer.Flush()  // ensure all writes written to disk before closing

Networking

Sockets

net.Dial() creates sockets of various types.

import "net"

// unix socketfile
conn, err = net.Dial("unix", "/var/tmp/foo.sock")

// inet socket
conn, err = net.Dial("tcp", "10.10.10.10:6600")
defer conn.Close()
// sending message to socket
_, err = conn.Write([]byte("search title 'it ceases to be'"))
reply := make([]byte, 1024)
_, err = conn.Read(reply)
fmt.Println(string(reply))

HTTP