Menu
flag Ar iconالعربيةdown icon

وسائط سطر الأوامر في Golang: os.Args وflag ومتغيّرات البيئة

كيف يقرأ برنامج Go سطر الأوامر: os.Args، الحزمة flag للخيارات ذات الأنواع، الأوامر الفرعية بـ FlagSet، متغيّرات البيئة بـ os.Getenv وos.LookupEnv، ورموز الخروج بـ os.Exit.

تحتوي هذه الصفحة على محررات قابلة للتشغيل - حرّر، شغّل، وشاهد النتيجة فوراً.

os.Args

os.Args شريحة من النصوص. os.Args[0] اسم البرنامج، والباقي هو الوسائط كما مرّرتها الصدفة (shell) تمامًا.

في لوحة Args في المحرّر كل حقل وسيط واحد يُمرَّر كما هو. جرّب hello وtwo words و-v في ثلاثة حقول: يرى البرنامج ثلاثة وسائط، ويبقى two words وسيطًا واحدًا بداخله مسافة. في الطرفية تتولّى الصدفة التقسيم، فالمكافئ هو go run . hello "two words" -v.

تحقّق دائمًا من len(os.Args) قبل الفهرسة. استخدام os.Args[1] دون وسائط يسبّب panic برسالة index out of range [1] with length 1.

الوسائط نصوص. حوّل الأرقام بـ strconv.Atoi أو strconv.ParseFloat وعالج الخطأ، فالمستخدمون يكتبون أي شيء.

الحزمة flag

للخيارات مثل -port 8080 -verbose استخدم flag. فهي تحلّل وتحوّل الأنواع وتبلغ عن الأخطاء وتولّد رسالة مساعدة.

دون وسائط يطبع هذا hello, world مرة واحدة. في لوحة Args جرّب -name وGopher في حقلين، ثم -count=3 و-loud وextra في ثلاثة حقول أخرى. يطبع البرنامج HELLO, GOPHER! ثلاث مرات ثم remaining args: [extra].

كيف تعمل الخيارات:

  • كل دالة تعريف (flag.String وflag.Int وflag.Bool وflag.Float64 وflag.Duration وflag.Uint64...) تأخذ اسمًا وقيمة افتراضية ونص استخدام، وتعيد مؤشرًا. اقرأ القيمة بـ *name بعد flag.Parse().
  • صيغ Var تربط الخيار بمتغيّر موجود لديك: flag.IntVar(&cfg.Port, "port", 8080, "port"). وهذا أرتب مع بنية إعدادات.
  • يمكن للمستخدمين كتابة -name value أو -name=value أو --name value أو --name=value. لا تفرّق Go بين شرطة واحدة وشرطتين.
  • الخيارات المنطقية تحتاج = لتأخذ قيمة. -loud تضبط true، و-loud=false تضبط false، أما -loud false فتضبط true وتترك false وسيطًا موضعيًا.
  • يتوقّف التحليل عند أول وسيط ليس خيارًا (أو عند --). في prog file.txt -v يُعامل -v وسيطًا موضعيًا. ضع الخيارات أولًا.
  • تعيد flag.Args() الوسائط الموضعية المتبقّية، وflag.NArg() عددها، وflag.Arg(i) واحدًا منها.

الخيار المجهول أو القيمة الخاطئة يطبع خطأ ونص الاستخدام، ويخرج بالحالة 2. أما -h أو -help فيطبع نص الاستخدام ويخرج بالحالة 0 (منذ Go 1.15). يُولَّد نص الاستخدام من تعريفاتك:

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.Usage على دالة لتطبع ترويستك الخاصة قبل استدعاء flag.PrintDefaults().

الأوامر الفرعية بـ FlagSet

أدوات مثل git commit -m msg لها أوامر فرعية بخيارات خاصة بها. أنشئ flag.FlagSet لكل أمر فرعي واختر أحدها بعبارة switch على الوسيط الأول:

يجعل flag.ContinueOnError الدالة Parse تعيد خطأ بدل الخروج، وهذا يبقي الدالة قابلة للاختبار. تأخذ run الوسائط معاملًا بدل قراءة os.Args، فيستطيع الاختبار استدعاء run([]string{"list", "-all"}) مباشرة. جرّب list و-all في لوحة Args، أو delete لترى مسار الخطأ.

لواجهات سطر الأوامر الكبيرة ذات الأوامر المتداخلة والإكمال التلقائي في الصدفة والتوثيق المولَّد، تستخدم معظم المشاريع المكتبة الخارجية github.com/spf13/cobra. أما الحزمة القياسية flag فتكفي الأدوات الصغيرة جيدًا.

متغيّرات البيئة

  • تعيد os.Getenv القيمة "" عندما يكون المتغيّر غير موجود وعندما يكون معرّفًا بنص فارغ على حد سواء. أما os.LookupEnv فتميّز بينهما.
  • القيم نصوص دائمًا. حوّلها وتحقّق منها عند بدء التشغيل، وافشل برسالة واضحة بدل الفشل في منتصف طلب.
  • تؤثّر os.Setenv في العملية الحالية والعمليات الفرعية التي تبدأ لاحقًا. ولا تستطيع تغيير بيئة الصدفة التي شغّلت برنامجك.
  • تعيد os.Environ() كل المتغيّرات على شكل نصوص "KEY=value".

ترتيب شائع للإعدادات: الخيارات لما يكتبه الإنسان، ومتغيّرات البيئة لإعدادات النشر (منصات الحاويات تضبطها)، والخيارات تتقدّم على البيئة، والبيئة تتقدّم على القيم الافتراضية.

رموز الخروج وos.Exit

يخرج برنامج Go بالحالة 0 عندما تعود main. تنهي os.Exit(code) العملية فورًا بتلك الحالة. اصطلاحًا 0 نجاح، و1 خطأ عام، و2 خطأ في الاستخدام (الحزمة flag تستخدم 2).

لا تنفّذ os.Exit الدوال المؤجّلة. لا تُفرَّغ الملفات ويُتخطّى تنظيف defer. تستدعي log.Fatal الدالة os.Exit(1) ولها الأثر نفسه. أبقِ os.Exit في مكان واحد، في نهاية main، وضع البرنامج الحقيقي في دالة run تعيد خطأ، كما يفعل مثال الأوامر الفرعية:

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

اكتب رسائل الخطأ إلى os.Stderr لا إلى os.Stdout، لتبقى ظاهرة عند توجيه المخرجات إلى ملف أو تمريرها إلى أمر آخر. الـ panic غير المستعاد يخرج بالحالة 2.

أخطاء شائعة

  • فهرسة os.Args دون التحقّق من طولها. الوسائط الناقصة تسبّب panic.
  • قراءة الخيارات قبل flag.Parse(). ستحصل على القيم الافتراضية.
  • نسيان *. تطبع fmt.Println(port) عنوانًا مثل 0xc000012345 لا القيمة.
  • وضع الخيارات بعد الوسائط الموضعية. في prog input.txt -v لا يُحلَّل -v.
  • كتابة -verbose false لخيار منطقي. اكتب -verbose=false.
  • استدعاء os.Exit أو log.Fatal في عمق البرنامج. لا يُنفَّذ التنظيف المؤجّل ولا يمكن اختبار الشيفرة. أعد الأخطاء صعودًا إلى main.

الأسئلة الشائعة

كيف أحصل على وسائط سطر الأوامر في Go؟

os.Args من النوع []string، يحمل اسم البرنامج في الفهرس 0 والوسائط بعده. os.Args[1:] هي الوسائط التي كتبها المستخدم. تحقّق من len(os.Args) قبل الفهرسة، وإلا سبّب البرنامج panic عند غياب وسيط.

كيف أستخدم الحزمة flag في Go؟

عرّف الخيارات، ثم استدعِ flag.Parse()، ثم اقرأها: port := flag.Int("port", 8080, "port to listen on")، ثم flag.Parse()، ثم fmt.Println(*port). تعيد الدوال مؤشرات. يكتب المستخدمون -port=9000 أو -port 9000 أو --port 9000، ويطبع -h نص الاستخدام المولَّد.

كيف أقرأ متغيّر بيئة في Go؟

تعيد os.Getenv("HOME") القيمة، أو نصًا فارغًا إذا لم يكن المتغيّر معرّفًا. للتمييز بين غير المعرّف والمعرّف بقيمة فارغة استخدم v, ok := os.LookupEnv("HOME"). تغيّر os.Setenv بيئة العملية الحالية والعمليات الفرعية التي تبدأها بعد ذلك.

هل تنفّذ os.Exit الدوال المؤجّلة في Go؟

لا. تنهي os.Exit العملية فورًا برمز الحالة المعطى، ولا تُنفَّذ الاستدعاءات المؤجّلة، فقد تضيع المخرجات المخزّنة ولا تُفرَّغ الملفات. النمط الشائع هو func main() { if err := run(); err != nil { fmt.Fprintln(os.Stderr, err); os.Exit(1) } }، مع وضع كل العمل الحقيقي وعبارات defer داخل run.

Coddy programming languages illustration

تعلّم البرمجة مع Coddy

ابدأ الآن