1---
2name: scripting-with-go
3description: Creates executable Go scripts with shebang-like behavior. Use when the user wants Go scripts, mentions Go scripting, or needs executable .go files. If working in a Go project, do NOT use unless explicitly requested.
4license: AGPL-3.0-or-later
5metadata:
6 author: Amolith <amolith@secluded.site>
7---
8
9Create executable Go scripts using a shell trick (not a true shebang). Scripts run directly like `./script.go` with full argument support.
10
11## Basic pattern
12
13First line of any Go script:
14
15```go
16/**/usr/local/go/bin/go run "$0" "$@"; exit;
17```
18
19Then `chmod +x script.go` and run `./script.go args`.
20
21## How it works
22
231. OS tries to execute `./script.go` as binary
242. Fails with ENOEXEC (not a binary)
253. OS falls back to `/bin/sh`
264. Shell runs first line: compiles and executes the script
275. `$0` = script path, `$@` = all arguments
286. `exit;` prevents shell from interpreting remaining Go code
297. `/**/` instead of `//` avoids gopls formatting complaints
30
31## Complete example
32
33```go
34/**/usr/local/go/bin/go run "$0" "$@"; exit;
35package main
36
37import (
38 "fmt"
39 "os"
40)
41
42func main() {
43 if len(os.Args) < 2 {
44 fmt.Println("Usage: ./script.go <name>")
45 os.Exit(1)
46 }
47 fmt.Printf("Hello, %s!\n", os.Args[1])
48}
49```
50
51## When to use
52
53**Good for:**
54- Long-lived automation needing stability (Go 1.x compatibility guarantee)
55- Cross-platform scripts
56- Corporate environments
57- Scripts that may grow into programs
58- Avoiding dependency management hell
59
60**Avoid for:**
61- Simple one-liners
62- Systems without Go
63- Throwaway scripts
64
65## Common patterns
66
67### CLI flags
68
69```go
70/**/usr/local/go/bin/go run "$0" "$@"; exit;
71package main
72
73import (
74 "flag"
75 "fmt"
76)
77
78func main() {
79 verbose := flag.Bool("v", false, "verbose output")
80 flag.Parse()
81 fmt.Printf("Verbose: %v, Args: %v\n", *verbose, flag.Args())
82}
83```
84
85### stdin
86
87```go
88/**/usr/local/go/bin/go run "$0" "$@"; exit;
89package main
90
91import (
92 "bufio"
93 "fmt"
94 "os"
95)
96
97func main() {
98 scanner := bufio.NewScanner(os.Stdin)
99 for scanner.Scan() {
100 fmt.Println("Got:", scanner.Text())
101 }
102}
103```
104
105### File operations
106
107```go
108/**/usr/local/go/bin/go run "$0" "$@"; exit;
109package main
110
111import (
112 "fmt"
113 "os"
114 "path/filepath"
115)
116
117func main() {
118 filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
119 if err != nil {
120 return err
121 }
122 if !info.IsDir() {
123 fmt.Println(path)
124 }
125 return nil
126 })
127}
128```
129
130## Notes
131
132- Adjust `/usr/local/go/bin/go` if Go is elsewhere
133- Semicolon required in `exit;` with `/**/` syntax
134- Avoid dependencies for maximum compatibility
135- Slower startup than interpreted languages (compilation time)