• Go फ़ाइलों को executable की तरह सीधे चलाने की एक ट्रिक का परिचय
  • पहली पंक्ति में //usr/local/go/bin/go run "$0" "$@"; exit रखें और execute permission दें, तो ./script.go से चलाया जा सकता है
  • यह तरीका shebang नहीं है, बल्कि POSIX में ENOEXEC होने पर shell के /bin/sh पर fallback करने वाले व्यवहार का उपयोग करता है
  • shell पहली पंक्ति को command की तरह चलाता है, और Go compiler उसे // comment मानकर नज़रअंदाज़ कर देता है
  • "$0" से अपनी ही path पास की जाती है, इसलिए go run script को build और execute करता है, और $@ से arguments पास होते हैं
  • Go की मज़बूत standard library और backward compatibility की गारंटी इसे scripting के लिए उपयुक्त बनाती है, और Go 1.x version इस्तेमाल करने पर script दशकों तक चल सकती है
  • Python के virtual environment, pip/poetry/uv जैसी dependency management की जटिलता से बचा जा सकता है

नकली shebang कैसे काम करता है

  • shebang(#!) execve system call के ज़रिए interpreter तय करने का तरीका है, लेकिन यहाँ बताई गई तकनीक shebang नहीं है
  • Go source file की पहली पंक्ति में //usr/local/go/bin/go run "$0" "$@"; exit रखकर, उसके नीचे package main और सामान्य Go code लिखा जाता है
    • chmod +x script.go से execute permission देने पर इसे ./script.go की तरह चलाया जा सकता है
  • strace से देखने पर पता चलता है कि shell जब ./script.go को execve से चलाने की कोशिश करता है, तो kernel ENOEXEC(Exec format error) लौटाता है
    • ENOEXEC मिलने पर shell fallback के तौर पर /bin/sh का उपयोग करके उसी फ़ाइल को shell script की तरह interpret करता है
    • shell में // comment नहीं है, बल्कि root path(/) की तरह interpret होता है, इसलिए //usr/local/go/bin/go एक वैध path की तरह execute हो जाता है
  • इसलिए पहली पंक्ति //usr/local/go/bin/go run "$0" "$@"; exit shell में command की तरह execute होती है
    • "$0" execute की गई फ़ाइल का path देता है, इसलिए command में "$0" script.go path बन जाता है और go run उसी फ़ाइल को ढूँढकर build और execute करता है
    • "$@" positional arguments expansion है, जिससे ./script.go -f flag0 here are some args जैसी invocation संभव होती है
    • ; exit न हो तो sh Go फ़ाइल को आगे भी लाइन-दर-लाइन interpret करता रहेगा और package जैसे token पर error देगा

Go scripting के लिए उपयुक्त क्यों है

  • Go की backward compatibility की गारंटी इसकी मुख्य विशेषताओं में से है, इसलिए Go 1.x इस्तेमाल करने पर लिखी गई script लंबे समय तक चलती रहती है
  • अच्छी तरह विकसित standard library और built-in tools (formatter, linter आदि) बिना अलग setup के मिलते हैं, जिससे script sharing और portability अधिकतम हो जाती है
    • Python की तरह virtual environment या अलग-अलग package managers (pip, poetry, uv) सीखे बिना code चलाया जा सकता है
    • Go ecosystem के built-in tools और IDE integration की वजह से .pyproject या package.json के बिना भी formatter और linter डिफ़ॉल्ट रूप से इस्तेमाल किए जा सकते हैं
  • अगर सिर्फ़ नया Go installed हो, तो किसी भी OS पर दशकों तक चलाया जा सकता है

दूसरी compiled languages से तुलना

  • Rust में compile speed धीमी है, standard library अपेक्षाकृत कमज़ोर है, dependency का उपयोग लगभग अनिवार्य हो जाता है, और perfectness पर ज़ोर होने से development speed धीमी पड़ती है
  • Java और JVM भाषाओं में पहले से JVM bytecode आधारित scripting languages मौजूद हैं, और हल्की Kotlin scripting भी एक विकल्प हो सकती है
  • compiled languages में Go के पास scripting use case के लिए सबसे उपयुक्त गुण हैं

gopls formatting समस्या और समाधान

  • gopls comment के बाद space मांगता है (//example// example), इसलिए नकली shebang लाइन टूट जाती है
  • space आ जाने पर // usr/local/go/bin/go बन जाता है, जिसे shell path की तरह नहीं पहचानता
  • समाधान: HN thread के सुझाव के अनुसार // की जगह /**/ block comment का उपयोग करें
    • इसे /*usr/local/go/bin/go run "$0" "$@"; exit; */ के रूप में लिखा जा सकता है
    • exit के बाद semicolon(;) अनिवार्य है

अभी कोई टिप्पणी नहीं है.

अभी कोई टिप्पणी नहीं है.