Menu

Golang Komut Satırı Argümanları: os.Args, flag ve Ortam Değişkenleri

Bir Go programı komut satırını nasıl okur: os.Args, tipli seçenekler için flag paketi, FlagSet ile alt komutlar, os.Getenv ve os.LookupEnv ile ortam değişkenleri ve os.Exit ile çıkış kodları.

Bu sayfada çalıştırılabilir editörler var - düzenle, çalıştır ve sonucu anında gör.

os.Args

os.Args bir string slice'ıdır. os.Args[0] programın adıdır, geri kalanı kabuğun aktardığı haliyle argümanlardır.

Editörün Args panelinde her alan bir argümandır ve olduğu gibi aktarılır. Üç alana hello, two words ve -v yazmayı deneyin: program üç argüman görür ve two words içinde boşluk olan tek bir argüman olarak kalır. Bir terminalde bölmeyi kabuk yapar, bu yüzden aynı şey go run . hello "two words" -v olur.

İndekslemeden önce her zaman len(os.Args)'ı kontrol edin. Argüman yokken os.Args[1], index out of range [1] with length 1 ile panic olur.

Argümanlar string'dir. Kullanıcılar her şeyi yazabileceği için sayıları strconv.Atoi ya da strconv.ParseFloat ile dönüştürün ve hatayı ele alın.

flag paketi

-port 8080 -verbose gibi seçenekler için flag kullanın. Ayrıştırır, tipleri dönüştürür, hataları bildirir ve bir yardım mesajı üretir.

Argümansız bu bir kez hello, world yazdırır. Args panelinde iki alana -name ve Gopher, sonra üç alana daha -count=3, -loud ve extra yazmayı deneyin. Program üç kez HELLO, GOPHER! ve remaining args: [extra] yazdırır.

Bayraklar nasıl çalışır:

  • Her tanımlayıcı (flag.String, flag.Int, flag.Bool, flag.Float64, flag.Duration, flag.Uint64...) bir ad, bir varsayılan ve bir kullanım string'i alır ve bir pointer döndürür. Değeri flag.Parse()'tan sonra *name ile okuyun.
  • Var biçimleri zaten sahip olduğunuz bir değişkene bağlanır: flag.IntVar(&cfg.Port, "port", 8080, "port"). Bu, bir yapılandırma struct'ı için daha düzenlidir.
  • Kullanıcılar -name value, -name=value, --name value ya da --name=value yazabilir. Go tek ve çift tire arasında ayrım yapmaz.
  • Boolean'lar bir değer almak için = ister. -loud true yapar, -loud=false false yapar, ama -loud false true yapar ve false'u konumsal bir argüman olarak bırakır.
  • Ayrıştırma bayrak olmayan ilk argümanda (ya da --'de) durur. prog file.txt -v, -v'yi konumsal bir argüman olarak ele alır. Bayrakları önce koyun.
  • flag.Args() kalan konumsal argümanları, flag.NArg() onların sayısını, flag.Arg(i) ise birini döndürür.

Bilinmeyen bir bayrak ya da hatalı bir değer bir hata artı kullanım metni yazdırır ve 2 durumuyla çıkar. -h ya da -help kullanım metnini yazdırır ve 0 durumuyla çıkar (Go 1.15'ten beri). Kullanım metni tanımlarınızdan üretilir:

Usage of greet:
  -count int
    	how many times (default 1)
  -delay duration
    	pause between greetings, e.g. 10ms
  -loud
    	shout the greeting
  -name string
    	who to greet (default "world")

flag.PrintDefaults()'u çağırmadan önce kendi başlığınızı yazdırmak için flag.Usage'ı bir fonksiyona ayarlayın.

FlagSet ile alt komutlar

git commit -m msg gibi araçların kendi bayrakları olan alt komutları vardır. Her alt komut için bir flag.FlagSet oluşturun ve ilk argüman üzerinde bir switch ile birini seçin:

flag.ContinueOnError, Parse'ın çıkmak yerine bir hata döndürmesini sağlar; bu da fonksiyonu test edilebilir tutar. run, os.Args'ı okumak yerine argümanları bir parametre olarak alır, böylece bir test doğrudan run([]string{"list", "-all"})'ı çağırabilir. Args panelinde list ve -all'ı ya da hata yolunu görmek için delete'i deneyin.

İç içe komutları, kabuk tamamlaması ve üretilmiş dokümanları olan büyük CLI'lar için çoğu proje üçüncü taraf github.com/spf13/cobra'yı kullanır. Standart flag paketi küçük araçları iyi karşılar.

Ortam değişkenleri

  • os.Getenv, hem değişken eksik olduğunda hem de boş bir string'e ayarlandığında "" döndürür. os.LookupEnv onları ayırt eder.
  • Değerler her zaman string'dir. Onları başlangıçta dönüştürüp doğrulayın ve bir isteğin ortasında değil, net bir mesajla başarısız olun.
  • os.Setenv mevcut süreci ve sonradan başlatılan alt süreçleri etkiler. Sizi başlatan kabuğun ortamını değiştiremez.
  • os.Environ() tüm değişkenleri "KEY=value" string'leri olarak döndürür.

Yapılandırma için yaygın bir düzen: bir kişinin yazdığı şeyler için bayraklar, dağıtım ayarları için ortam değişkenleri (container platformları onları ayarlar); bayraklar ortamı, ortam da varsayılanları geçersiz kılar.

Çıkış kodları ve os.Exit

Bir Go programı main döndüğünde 0 durumuyla çıkar. os.Exit(code) süreci o durumla hemen sonlandırır. Geleneğe göre 0 başarı, 1 genel bir hata, 2 ise bir kullanım hatasıdır (flag paketi 2 kullanır).

os.Exit ertelenmiş fonksiyonları çalıştırmaz. Dosyalar flush edilmez ve defer temizliği atlanır. log.Fatal, os.Exit(1)'i çağırır ve aynı etkiye sahiptir. os.Exit'i tek bir yerde, main'in sonunda tutun ve asıl programı, alt komut örneğinin yaptığı gibi, bir hata döndüren bir run fonksiyonuna koyun:

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

Hata mesajlarını os.Stdout'a değil os.Stderr'e yazın, böylece çıktı bir dosyaya yönlendirildiğinde ya da başka bir komuta pipe edildiğinde görünür kalırlar. Recover edilmemiş bir panic 2 durumuyla çıkar.

Sık yapılan hatalar

  • Uzunluğunu kontrol etmeden os.Args'ı indekslemek. Eksik argümanlar panic'e yol açar.
  • Bayrakları flag.Parse()'tan önce okumak. Varsayılanları alırsınız.
  • *'ı unutmak. fmt.Println(port) değeri değil, 0xc000012345 gibi bir adres yazdırır.
  • Bayrakları konumsal argümanlardan sonra koymak. prog input.txt -v, -v'yi ayrıştırmaz.
  • Bir bool bayrak için -verbose false. -verbose=false yazın.
  • Programın derinliklerinde os.Exit ya da log.Fatal çağırmak. Ertelenmiş temizlik hiç çalışmaz ve kod test edilemez. Hataları main'e kadar döndürün.

Sıkça Sorulan Sorular

Go'da komut satırı argümanları nasıl alınır?

os.Args, 0. indekste program adını ve ardından argümanları tutan bir []string'dir. os.Args[1:] kullanıcının yazdığı argümanlardır. İndekslemeden önce len(os.Args)'ı kontrol edin; aksi halde bir argüman eksik olduğunda program panic olur.

Go'da flag paketi nasıl kullanılır?

Bayrakları tanımlayın, flag.Parse()'ı çağırın, sonra onları okuyun: port := flag.Int("port", 8080, "port to listen on"), flag.Parse(), fmt.Println(*port). Fonksiyonlar pointer döndürür. Kullanıcılar -port=9000, -port 9000 ya da --port 9000 yazar ve -h üretilen kullanım metnini yazdırır.

Go'da bir ortam değişkeni nasıl okunur?

os.Getenv("HOME") değeri, değişken ayarlanmamışsa boş bir string döndürür. Ayarlanmamış ile boşa ayarlanmış olanı ayırt etmek için v, ok := os.LookupEnv("HOME") kullanın. os.Setenv mevcut sürecin ve sonradan başlattığı alt süreçlerin ortamını değiştirir.

Go'da os.Exit ertelenmiş fonksiyonları çalıştırır mı?

Hayır. os.Exit süreci verilen durum koduyla hemen sonlandırır ve ertelenmiş çağrılar çalışmaz, bu yüzden buffer'daki çıktı kaybolabilir ve dosyalar flush edilmeyebilir. Yaygın bir kalıp func main() { if err := run(); err != nil { fmt.Fprintln(os.Stderr, err); os.Exit(1) } } şeklindedir; asıl iş ve tüm defer'ler run içindedir.

Coddy programming languages illustration

Coddy ile kodlamayı öğren

BAŞLA