3 minutes
WC implementation in Go Lang
Continuing the theme of exploring Go Lang, today I will be writing a simple version
of the Unix
utility wc
that displays the number of lines, words, and bytes contained in each
input file.
This exploration process will involve the following pieces
- Getting a file name from command line. os
- Opening the file for reading. os
- Reading the contents of the file. bufio
- Count the lines, words and bytes. unicode
- Display the results.
1. Read filename from the commandline
Any arguments typed after the programs named are passed into the os.Args
array
with the name of the program accessible at the first index.
var fileName string
if len(os.Args) > 1 {
fileName = os.Args[1]
} else {
fmt.Println("Please pass a file name")
os.Exit(1)
}
2. Open the file
Once you have the name of the file, it can be simply opened using the "os.Open()"
function
in the os
package. If the open fails, the error string will be self-explanatory.
file, err := os.Open(fileName)
if err != nil {
fmt.Println("Err ", err)
}
#
🤓 Explore the os
package as part of getting familiar with Go Lang.
3. Read the contents of the file
There are quite a few ways of reading the contents of the file. In this post I will be using the bufio
package to read the contents of the file line by line using NewScanner()
.
In the code snippet below, we are scanning the file line by line and printing the output to the console.
scanner := bufio.NewScanner(file)
lines, words, characters := 0, 0, 0
for scanner.Scan() {
fmt.Println(scanner.Text())
}
4. Analyze the file content
Finally, we need to keep track of the lines in the file, and the number or words in each line.
The total byte/characters will be the summation of length of each line
we iterate while reading the file. And to compute the number of words
we can simply split the line based on whitespace
and count the total
number of such splits.
scanner := bufio.NewScanner(file)
lines, words, characters := 0, 0, 0
for scanner.Scan() {
lines++
line := scanner.Text()
characters += len(line)
splitLines := strings.Split(line, " ")
words += len(splitLines)
}
4. Display
Once, we have compute the word count, it can be displayed on the cosole using
the fmt
.
fmt.Printf("%8d%8d%8d %s\n", lines, words, characters, fileName)
Full program listing
This is the complete listing of the program implementing the WC
utility in Go Lang.
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
var fileName string
if len(os.Args) > 1 {
fileName = os.Args[1]
} else {
fmt.Println("Please pass a file name")
os.Exit(1)
}
file, err := os.Open(fileName)
if err != nil {
fmt.Println("Err ", err)
}
scanner := bufio.NewScanner(file)
lines, words, characters := 0, 0, 0
for scanner.Scan() {
lines++
line := scanner.Text()
characters += len(line)
splitLines := strings.Split(line, " ")
words += len(splitLines)
}
fmt.Printf("%8d%8d%8d %s\n", lines, words, characters, fileName)
}
#
🤓 Explore the wc
utility and try to finish up the missing pieces.