Go
Challenge 4 - CLI tool
Write a CLI tool that processes files with flag.
Challenge: a line-counting tool
You will write a CLI tool similar to Unix wc. Rules: with -l it prints only the line count; without it, the line, word and byte counts. Input is read from stdin; so it can be tested, all logic lives in a run(args, in, out) function.
printf "a b\nc\n" | ./say # 2 3 6
printf "a b\nc\n" | ./say -l # 2
Plan
1) A -l bool option with a FlagSet. 2) veri, err := io.ReadAll(in). 3) Lines: bytes.Count(veri, []byte("\n")); words: len(strings.Fields(string(veri))); bytes: len(veri). 4) With -l write only the line count, otherwise all three with fmt.Fprintln(out, ...). 5) In main, on error write to stderr and os.Exit(1).
Exercise Write the tool
Implement the plan. In main, call run(nil, strings.NewReader("a b\nc\n"), os.Stdout) and run([]string{"-l"}, strings.NewReader("a b\nc\n"), os.Stdout).
Show example solution
package main
import (
"bytes"
"flag"
"fmt"
"io"
"os"
"strings"
)
func run(args []string, in io.Reader, out io.Writer) error {
fs := flag.NewFlagSet("say", flag.ContinueOnError)
l := fs.Bool("l", false, "yalnızca satır sayısı")
if err := fs.Parse(args); err != nil {
return err
}
veri, err := io.ReadAll(in)
if err != nil {
return err
}
lines := bytes.Count(veri, []byte("\n"))
if *l {
_, err = fmt.Fprintln(out, lines)
return err
}
_, err = fmt.Fprintln(out, lines, len(strings.Fields(string(veri))), len(veri))
return err
}
func main() {
for _, a := range [][]string{nil, {"-l"}} {
if err := run(a, strings.NewReader("a b\nc\n"), os.Stdout); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
}
Test yourself
-
Which gives the byte count most accurately?
- utf8.RuneCount
- Read all input and take len(veri)
- Summing the line lengths
- Word count × 5
Show answer
Read all input and take len(veri) — A Scanner drops line endings, so summing line lengths misses the \n bytes. RuneCount counts characters, not bytes.
-
Count the lines
lines := bytes.____(veri, []byte("
"))
Show answer
lines := bytes.Count(veri, []byte("
"))
-
Measurement and method
- Line
- bytes.Count(\n)
- Kelime
- strings.Fields
- Bayt
- len(veri)
- Karakter
- utf8.RuneCount
Next lesson: Intermediate section exam