Input and Output in Go
In Go, input/output (I/O) refers to the methods by which a program communicates with other systems, including files, networks, the console (standard input/output/error), and other programs. For managing a variety of I/O activities, Go offers strong and thoroughly documented libraries with a focus on a clear and consistent interface design.
Core I/O Interfaces and Packages
The core interfaces for reading and writing data are defined by the io package, which forms the basis of Go’s I/O system. Many functions in Go accept or return these generic I/O types, therefore these interfaces enable very flexible and reusable programming.
io.Reader
: Reading data is supported via the Read method defined in this interface. As an input source, any type that implements this technique can be utilized.- The Read() method must be implemented by a type in order to satisfy io.Reader.
io.Writer
: Writing data is supported by the Write method defined in this interface. The destination for output can be any type that implements this method.- A type must implement a single method called Write() in order to satisfy io.Writer.
io.Copy
: This high-level function effectively transfers data between an io.Reader and an io.Writer.- Copying the contents of a file or rerouting standard input to standard output are two common uses for this.
Standard I/O (Console Interaction)
The operating system’s features, including as standard input, output, and error streams, are accessible through the os package.
os.Stdin
: Symbolizes the standard input stream, which is usually the keyboard.
os.Stdout
: The standard output stream, usually the terminal display, is represented by this.
os.Stderr
: Usually the terminal display, but with error messages split, this represents the standard error stream.
Outputting to Standard Output
Formatted input and output, particularly for printing to the screen, are frequently handled by the fmt package.
fmt.Println()
: Prints a newline after the arguments, which are separated by spaces.fmt.Print()
: Though it does not instantly add a new line, it is comparable to Println().fmt.Printf()
: Uses “verbs” (format specifiers) to enable formatted output, much to C’s printf.io.WriteString()
: A function that writes a string to an io.Writer is part of the io package.fmt.Sprintln()
,fmt.Sprint()
, andfmt.Sprintf()
are used for creating strings, whilefmt.Fprintln()
,fmt.Fprint()
, andfmt.Fprintf()
are used for writing to files using anio.Writer
.
Outputting to Standard Error
Sending data to standard error is possible in Go in order to distinguish between actual values and error output.
package main
import (
"io"
"os"
)
func main() {
myString := "An error occurred!"
io.WriteString(os.Stderr, myString) // Writes the error message to standard error
io.WriteString(os.Stderr, "\n")
}
Output
An error occurred!
Reading from Standard Input:
The bufio package is frequently used for reading from standard input and other effective, buffered I/O.
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
scanner := bufio.NewScanner(os.Stdin) // Creates a new scanner for standard input
fmt.Print("Enter text: ")
for scanner.Scan() { // Reads input line by line
fmt.Println(">", scanner.Text()) // Prints the read line
fmt.Print("Enter text: ")
}
// In Unix, you can tell a program to stop reading data from standard input by pressing Ctrl + D .
}
Output
Enter text: Govindhtech Solutions
> Govindhtech Solutions
Enter text: 2023
> 2023
Enter text: Govindhtech
> Govindhtech
Enter text:
File I/O
Additionally, the OS package has routines for opening, creating, reading, and writing files, among other file system operations.
os.Open()
: Lets you read a file.
os.Create()
: Makes a writing file and, if it already exists, truncates it.
io.ReadString()
: Pulls information from a bufio.Read until a delimiter (such as \n) appears.
f.Read(buffer)
: Reads from a file a predetermined number of bytes into a byte slice.
fmt.Fprintln(f, ...)
: io.Writer
is a program that writes formatted data to a file.
Example of Reading a File Line by Line:
package main
import (
"bufio"
"fmt"
"io"
"os"
)
func lineByLine(file string) error {
f, err := os.Open(file) // Open the file [46]
if err != nil {
return err
}
defer f.Close() // Ensure the file is closed after the function returns [46]
r := bufio.NewReader(f) // Create a new buffered reader [46]
for {
line, err := r.ReadString('\n') // Read line by line until newline character [46]
if err == io.EOF { // End of file [46, 49]
fmt.Print(line) // Print the last line if it exists
break
} else if err != nil {
fmt.Printf("error reading file %s", err)
break
}
fmt.Print(line) // Print the read line [46]
}
return nil
}
func main() {
// Example usage: create a dummy file
dummyFile, _ := os.Create("test.txt")
dummyFile.WriteString("First line\nSecond line\nThird line")
dummyFile.Close()
err := lineByLine("test.txt")
if err != nil {
fmt.Println("Error:", err)
}
os.Remove("test.txt") // Clean up
}
Output
First line
Second line
Third line
Example of Reading a Specific Amount of Data from a File:
package main
import (
"fmt"
"io"
"os"
)
func readSize(f *os.File, size int) []byte {
buffer := make([]byte, size) // Create a byte slice of the desired size [44]
n, err := f.Read(buffer) // Read bytes into the buffer [49]
if err == io.EOF {
return nil
}
if err != nil {
fmt.Println(err)
return nil
}
return buffer[0:n] // Return only the bytes that were actually read [49]
}
func main() {
dummyFile, _ := os.Create("data.txt")
dummyFile.WriteString("Hello Go I/O!")
dummyFile.Close()
f, err := os.Open("data.txt")
if err != nil {
fmt.Println(err)
return
}
defer f.Close()
data := readSize(f, 5) // Read 5 bytes
fmt.Printf("Read: %s\n", string(data)) // Output: Read: Hello
data = readSize(f, 3) // Read another 3 bytes
fmt.Printf("Read: %s\n", string(data)) // Output: Read: Go
os.Remove("data.txt")
}
Output
Read: Hello
Read: Go
String and Byte Slice I/O
Strings and byte slices can act like I/O streams with Go’s strings and bytes packages, which also offer I/O-related features.
strings.NewReader()
: Generates an io.a string reader. Compared to using bytes, this is more effective when reading from a string.Create a buffer.
bytes.Buffer
: A read-write buffer of bytes with a changeable size. Both io.Reader and io.Writer interfaces are supported, and it doesn’t require initialisation. By using buf.Bytes(), you can change it to a []byte.
Error Handling in I/O
Managing errors is essential for Go I/O operations. An error type is returned by the majority of I/O functions (or nil if no error occurred). Developers need to be aware of these mistakes and take appropriate action. Io.EOF, which denotes the end of the input, is a common mistake to look for while reading from a stream or file.
You can also read What Is Mean By Documentation In Golang With Code Examples