Özet - flag paketi
- Go kursu
- Orta seviye
- Ders 76/80
- 4 dk
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.
Başlangıç kodu
package main
import (
"bufio"
"flag"
"fmt"
"io"
"os"
"strings"
)
func main() {
// buraya yaz
}Örnek çözüm
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)
}
}Beklenen çıktı
go go
Soru ve cevaplar
Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.
1 <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 Doğru cevap
- Daha hızlı çalışır
Açıklama: Argümanlar, girdi ve çıktı parametre olduğu için testte dilim, strings.Reader ve bytes.Buffer verilir.
2 Seçenekleri listele
flag.Usage = func() {
fmt.Fprintln(os.Stderr, "kullanım: app [seçenekler]")
flag.____()
}
flag.Usage = func() {
fmt.Fprintln(os.Stderr, "kullanım: app [seçenekler]")
flag.PrintDefaults()
}
Açıklama: PrintDefaults tüm seçenekleri açıklama ve varsayılanlarıyla yazdırır.
3 Grubun özeti
| Kavram | Anlamı |
|---|---|
flag.Int |
Seçenek tanımı |
flag.Args() |
Konumsal argümanlar |
FlagSet |
Alt komut |
os.Exit(2) |
Kullanım hatası |