Go
Özet - flag paketi
flag ve os.Args'ı birleştirerek bir CLI aracı yazarsın.
CLI özeti
İyi bir komut satırı aracı: seçenekler için flag (-h ile otomatik yardım), konumsal argümanlar için flag.Args(), alt komutlar için ayrı FlagSet'ler, dosya verilmezse stdin'den okuma, sonuçları stdout'a ve hataları stderr'e yazma, başarıda 0, hatada 1, kullanım hatasında 2 çıkış kodu.
func main() {
if err := run(os.Args[1:], os.Stdin, os.Stdout); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
Sinyal ve iptal
Uzun çalışan bir araç Ctrl+C ile durdurulduğunda geçici dosyaları temizlemelidir. signal.NotifyContext sinyali context iptaline çevirir:
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
defer stop()
if err := isle(ctx); errors.Is(err, context.Canceled) {
fmt.Fprintln(os.Stderr, "iptal edildi")
os.Exit(130)
}
130, Ctrl+C ile kesilen programlar için geleneksel çıkış kodudur.
Uygulama run fonksiyonu
run(args []string, in io.Reader, out io.Writer) error yaz: -n (int, varsayılan 1) seçeneğini kendi FlagSet'iyle ayrıştırsın, girdinin ilk satırını bufio.Scanner ile okuyup n kez out'a yazsın. run([]string{"-n=2"}, strings.NewReader("go\n"), os.Stdout) ile çağır.
Örnek çözümü göster
package main
import (
"bufio"
"flag"
"fmt"
"io"
"os"
"strings"
)
func run(args []string, in io.Reader, out io.Writer) error {
fs := flag.NewFlagSet("tekrar", flag.ContinueOnError)
n := fs.Int("n", 1, "tekrar sayısı")
if err := fs.Parse(args); err != nil {
return err
}
sc := bufio.NewScanner(in)
if !sc.Scan() {
return sc.Err()
}
for i := 0; i < *n; i++ {
fmt.Fprintln(out, sc.Text())
}
return nil
}
func main() {
if err := run([]string{"-n=2"}, strings.NewReader("go\n"), os.Stdout); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
Kendini test et
-
<code>run(args, stdin, stdout)</code> deseni neden yaygındır?
- flag paketi bunu zorunlu tutar
- Daha az kod gerektirir
- Aracın tamamı os paketine dokunmadan test edilebilir
- Daha hızlı çalışır
Cevabı göster
Aracın tamamı os paketine dokunmadan test edilebilir — Argümanlar, girdi ve çıktı parametre olduğu için testte dilim, strings.Reader ve bytes.Buffer verilir.
-
Seçenekleri listele
flag.Usage = func() {
fmt.Fprintln(os.Stderr, "kullanım: app [seçenekler]")
flag.____()
}
Cevabı göster
flag.Usage = func() {
fmt.Fprintln(os.Stderr, "kullanım: app [seçenekler]")
flag.PrintDefaults()
}
-
Grubun özeti
- flag.Int
- Seçenek tanımı
- flag.Args()
- Konumsal argümanlar
- FlagSet
- Alt komut
- os.Exit(2)
- Kullanım hatası
Sıradaki ders: Meydan okuma 1 - Eşzamanlılık