முக்கிய உள்ளடக்கத்திற்குச் செல்லவும்
தொகுதி 10 · பாடம் 4 இன் 5பாடத்திட்டத்தில் 49/50~18 min
தொகுதி பாடங்கள் (4/5)

சிறு திட்டம்: கொடிகள் கொண்ட ஒரு CLI

flag தொகுப்பைக் கொண்டு கொடி பாகுபடுத்துதல், os.Stderr இல் பிழைகள், மற்றும் சரியான வெளியேறும் குறியீடு ஆகியவற்றைக் கொண்டு ஒரு சிறிய idiomatic CLI ஐ உருவாக்க முந்தைய தொகுதிகளின் கட்டுமானத் தொகுதிகளை ஒன்றாக இணைப்போம்.

flag தொகுப்பு

Go
package main

import (
    "flag"
    "fmt"
    "os"
)

func main() {
    n := flag.Int("n", 1, "number of repetitions")
    upper := flag.Bool("u", false, "print in uppercase")
    flag.Parse()

    args := flag.Args() // remaining positional arguments
    if len(args) < 1 {
        fmt.Fprintln(os.Stderr, "usage: echo [-n N] [-u] <text>")
        os.Exit(2)
    }

    text := args[0]
    if *upper {
        text = strings.ToUpper(text)
    }
    for i := 0; i < *n; i++ {
        fmt.Println(text)
    }
}

முக்கிய புள்ளிகள்:

  • flag.Int, flag.String, flag.Bool, flag.Duration (முதலியன.) சுட்டி: நீங்கள் *n, AGYTOK_8INLINE_INLINE__ஐப் பயன்படுத்துகிறீர்கள்.
  • flag.Parse() மதிப்புகளைப் படிக்கும் முன் மற்றும் flag.Args()க்கு முன் ஒருமுறை அழைக்கப்பட வேண்டும்.
  • flag.Args() நிலை தருமதிப்புகளை (--க்குப் பின் அல்லது கடைசிக் கொடிக்குப் பின்) வழங்கும்.
  • ஏற்றுக்கொள்ளப்பட்ட படிவங்கள்: -n 3, -n=3, --n=3. பூலியன்கள்: -u (உண்மை), -u=false.

வழக்கமான வெளியேறும் குறியீடுகள்

Go
os.Exit(0) // success
os.Exit(1) // generic error
os.Exit(2) // usage error (incorrect flag usage)

ஷெல்களும் ஸ்கிரிப்ட்களும் இந்தக் குறியீடுகளை எதிர்பார்க்கின்றன: அவற்றைத் தொடர்ந்து பயன்படுத்தவும். ஒருபோதும் os.Exit உடன் முக்கிய அல்லாத கோரூட்டினிலிருந்து வெளியேறவும்: இது log ஃப்ளஷிங் உட்பட ஒவ்வொரு defer ஐயும் தவிர்க்கிறது.

Stderr vs Stdout

பழைய மற்றும் புனிதமான யூனிக்ஸ் விதி:

  • os.Stdout → பயனுள்ள வெளியீடு, குழாய் திறன் (cli | grep ...).
  • os.Stderr → கண்டறிதல், பிழைகள், முன்னேற்றப் பட்டைகள், பயன்பாடு.
Go
fmt.Println("result: 42")                   // stdout
fmt.Fprintln(os.Stderr, "error: ...")       // stderr

இந்த வழியில் cli 2>/dev/null முடிவுகளை மட்டுமே காட்டுகிறது, cli >out.txt முடிவை மட்டும் திசைதிருப்புகிறது மற்றும் பிழைகள் தெரியும்.

log எதிராக fmt

  • fmt பயனர் வெளியீட்டிற்கு.
  • log நோயறிதலுக்காக: நேர முத்திரையைச் சேர்க்கிறது, இயல்பாக os.Stderr க்கு எழுதுகிறது, log.Fatal (பதிவுகள் + os.Exit(1)) மற்றும் AGYTOK_34INLINE_LINE_34.
Go
log.SetFlags(log.LstdFlags | log.Lshortfile) // timestamp + file:line
log.Fatal("boom") // prints and exits with 1

நவீன பயன்பாடுகளுக்கு (Go 1.21+) log/slog கட்டமைக்கப்பட்ட பதிவுகளுக்கு (JSON அல்லது உரை, நிலைகள், தட்டச்சு செய்த புலங்கள்) பயன்படுத்தவும்.

கட்டிடக்கலை: லாஜிக்கிலிருந்து main பிரிக்கவும்

Go
func main() {
    if err := run(os.Args[1:], os.Stdout, os.Stderr); err != nil {
        fmt.Fprintln(os.Stderr, err)
        os.Exit(1)
    }
}

func run(args []string, stdout, stderr io.Writer) error {
    // here use a new flag.FlagSet instead of the global flag.CommandLine
    fs := flag.NewFlagSet("echo", flag.ContinueOnError)
    fs.SetOutput(stderr)
    n := fs.Int("n", 1, "repetitions")
    if err := fs.Parse(args); err != nil {
        return err
    }
    // ...
    return nil
}

நன்மைகள்:

  • சோதனை: நீங்கள் bytes.Buffer ஐ stdout/stderr ஆக கடந்து, வெளியீட்டைச் சரிபார்க்கவும்.
  • உலகளாவிய நிலை இல்லை: ஒவ்வொரு FlagSet தனிமைப்படுத்தப்பட்டுள்ளது.
  • main சிறியதாக இருக்கும்: இது IO + பிரதிநிதிகளைத் தயார்படுத்துகிறது.

துணைக் கட்டளைகள்

துணைக் கட்டளைகளைக் கொண்ட CLIகளுக்கு (mycli serve, mycli migrate), வெளிப்புற சார்புகள் இல்லாத திட்டம்:

Go
func main() {
    if len(os.Args) < 2 {
        usage()
        os.Exit(2)
    }
    switch os.Args[1] {
    case "serve":
        serveCmd(os.Args[2:])
    case "migrate":
        migrateCmd(os.Args[2:])
    default:
        usage()
        os.Exit(2)
    }
}

ஒவ்வொரு துணைக் கட்டளைக்கும் அதன் சொந்த flag.NewFlagSet உள்ளது. பெரிய திட்டங்களுக்கு, cobra அல்லது urfave/cli போன்ற நூலகங்கள் தானாக உருவாக்கப்பட்ட உதவியுடன் இந்தத் திட்டத்தை வடிவமைக்கின்றன.

பயிற்சிகள்

உடற்பயிற்சி#go.m10.l4.e1
முயற்சிகள்: 0ஏற்றுகிறது…

Definisci il flag -n di tipo int con valore di default 1 e descrizione 'ripetizioni', poi chiama flag.Parse() e Stampa il valore.

எடிட்டரை ஏற்றுகிறது…

3 முயற்சிகளுக்குப் பிறகு தீர்வு கிடைக்கும்

உடற்பயிற்சி#go.m10.l4.e2
முயற்சிகள்: 0ஏற்றுகிறது…

Se non c'è almeno un argomento posizionale dopo flag. Parse, Stampa 'manca argomento' su Stderr e termina con os.Exit(1).

எடிட்டரை ஏற்றுகிறது…

3 முயற்சிகளுக்குப் பிறகு தீர்வு கிடைக்கும்

Quiz#go.m10.l4.e3
தயார்

ஒரு CLI யூனிக்ஸ்-நட்பு இல் க்வாலே ஸ்ட்ரீம் ஸ்டாம்பி மெசக்கி டி பிழை மற்றும் பயன்பாடு?

Go
fmt.Fprintln(???, "uso: prog ...")
பதில் விருப்பங்கள்