Need help?
<- Back

Comments (80)

  • hamishwhc
    The author’s point about “not caring about pip vs poetry vs uv” is missing that uv directly supports this use case, including PyPI dependencies, and all you need is uv and your preferred Python version installed: https://docs.astral.sh/uv/guides/scripts/#using-a-shebang-to...
  • fsmv
    I made one of these too! I decided not to use // because I use gofmt auto formatting in my editor and it puts a space between the // and the usr. This one isn't changed by gofmt: /*?sr/bin/env go run "$0" "$@"; exit $? #*/
  • PaulRobinson
    Mad genius stuff, this.However... scripting requires (in my experience), a different ergonomic to shippable software. I can't quite put my finger on it, but bash feels very scriptable, go feels very shippable, python is somewhere in the middle, ruby is closer to bash, rust is up near go on the shippable end.Good scripting is a mixture of OS-level constructs available to me in the syntax I'm in (bash obviously is just using OS commands with syntactic sugar to create conditional, loops and variables), and the kinds of problems where I don't feel I need a whole lot of tooling: LSPs, test coverage, whatever. It's languages that encourage quick, dirty, throwaway code that allows me to get that one-off job done the guy in sales needs on a Thursday so we can close the month out.Go doesn't feel like that. If I'm building something in Go I want to bring tests along for the ride, I want to build a proper build pipeline somewhere, I want a release process.I don't think I've thought about language ergonomics in this sense quite like this before, I'm curious what others think.
  • flufluflufluffy
    I don’t really understand the initial impetus. I like scripting in Python. That’s one of the things it’s good at. You can extremely quickly write up a simple script to perform some task, not worrying about types, memory, yada yada yada. I don’t like using Python as the main language for a large application.
  • g947o
    While you are at it, might as well do this for C++ or assembly. You hate scripting so much and would rather go to great lengths to use a complied language and throw away all the benefits of a scripting language and scripting itself, just because you don't like the language, not because of technical merit. Congratulations, you just wasted yourself many hours of precious time.> The price of convenience is difficulties to scaleOf course, they never scale. The moment you start thinking about scaling, you should stop writing code as throwaway scripts but build them properly. That's not an argument to completely get rid of Python or bash. The cost of converting Python code to Go is near zero these days if there is a need to do so. Enough has been said about premature optimization.> Anyone who's ever tried to get python working on different systems knows what a steep annoying curve it is.If you need 10 libraries of certain versions to run a few lines of Python code, nobody calls that a script anymore. It becomes a proper project that requires proper package management, just like Go.
  • itopaloglu83
    > Sidetrack: I actually looked up what the point of arg0 even is since I failed to find any usecases some months back and found this answer.I think arg0 was always useful especially when developing multifunctional apps like busybox that changes its behavior depending on the name it was executed as.
  • llmslave2
    I love it. I'm using Go to handle building full stack javascript apps, which actually works great since esbuild can be used directly inside a Go program. The issue is that it's a dependency, so I settled for having a go mod file and running it directly with Go. If somehow these dependencies could be resolved without an explicit module configured (say, it was inline in the go file itself) it would be perfect. Alas, it will probably never happen.That being said...use Go for scripting. It's fantastic. If you don't need any third party libraries this approach seems really clean.
  • esjeon
    Expected a rant, got a life-pro-tip. Enough for a good happy new year.That said, we can abuse the same trick for any languages that treats `//` as comment.List of some practical(?) languages: C/C++, Java, JavaScript, Rust, Swift, Kotlin, ObjC, D, F#, GLSL/HLSL, GroovyPersonally, among those languages, GLSL sounds most interesting. A single-GLSL graphics demo is always inspiring. (Something like https://www.shadertoy.com/ )Also, let’s not forget that we can do something similar using block comment(`/* … */`). An example in C:/*/../usr/bin/env gcc "$0" "$@"; ./a.out; rm -vf a.out; exit; */#include <stdio.h>int main() { printf("Hello World!\n"); return 0; }
  • rtpg
    You don't even need to end the file in `.go` or the like when using shebangs, and any self-respecting editor will be good at parsing out shebangs to identify file types (... well, Emacs seems to do it well enough for me)no need to name your program foo.go when you could just name it foo
  • magicalhippo
    You can do the same[1] with .Net Core for those of us who like that.[1]: https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals...
  • marifjeren
    > don't want to have virtual environments and learn what the difference between pip, poetry and uv isOh come on, it's easy:Does the project have a setup.py? if so, first run several other commands before you can run it. python -m venv .venv && source .venv/bin/activate && pip install -e .else does it have a requirements.txt? if so python -m venv .venv && source .venv/bin/activate && pip install -r requirements.txtelse does it have a pyproject.toml? if so poetry install and then prefix all commands with poetry run ...else does it have a pipfile? pipenv install and then prefix all commands with pipenv run ...else does it have an environment.yml? if so conda env create -f environment.yml and then look inside the file and conda activate <environment_name>else does it have a uv.ock? then uv sync (or uv pip install -e .) and then prefix commands with uv run.
  • networked
    You can use https://github.com/erning/gorun as a Go script runner. It lets you embed `go.mod` and `go.sum` and have dependencies in Go scripts. This is more verbose than Python's inline script metadata and requires manual management of checksums.Example: /// 2>/dev/null ; gorun "$0" "$@" ; exit $? // // go.mod >>> // module foo // go 1.22 // require github.com/fatih/color v1.16.0 // require github.com/mattn/go-colorable v0.1.13 // require github.com/mattn/go-isatty v0.0.20 // require golang.org/x/sys v0.14.0 // <<< go.mod // // go.sum >>> // github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= // github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= // github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= // github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= // github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= // github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= // github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= // golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= // golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= // golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= // golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= // <<< go.sum package main import "github.com/fatih/color" func main() { color.Green("Hello, world!") }
  • age123456gpg
    Official stance about supporting interpreter mode for the reference https://github.com/golang/go/issues/24118
  • w4rh4wk5
    Back in the days, I've seen that with C files, which are compiled on the fly to a temporary file an run.Something like //usr/bin/gcc -o main "$0"; ./main "$@"; exit
  • jas39
    May I...augroup fix autocmd! autocmd BufWritePost *.go \ if getline(1) =~# '^// usr/bin/' \ | call setline(1, substitute(getline(1), '^// ', '//', '')) \ | silent! write \ | endif augroup END
  • xg15
    So the entire reason why this is not a "real" shebang and instead takes the roundtrip through the shell is because the Go runtime would trip over the # character?I think this points to some shortcomings of the shebang mechanism itself: That it expects the shebang line to be present and adhering a specific structure - but then passes the entire file with the line to the interpreter where the interpreter has to process (and hopefully ignore) the line again.I know that situations where one piece of text is parsed by multiple different systems are intellectually interesting and give lots of opportunities for cleverness - but I think the straightforward solution would be to avoid such situations.So maybe the linux devs should consider adding a new form for the shebang where the first line is just stripped before passing the file contents to the interpreter.
  • liveoneggs
    what's even cooler is when the language comes with first class support for this: https://www.erlang.org/docs/18/man/escriptOr the venerable https://babashka.org/
  • chrismorgan
    One suggestion: change `exit` to `exit $?` so an exit code is passed back to the shell.
  • emersion
    The following would probably be more portable: ///usr/bin/env go run "$0" "$@"; exit Note, the exit code isn't passed through due to: https://github.com/golang/go/issues/13440
  • throw-12-16
    I've been meaning to port some dotfiles utils over to go, I think I'll give this a shot.
  • anon
    undefined
  • rubymamis
    What about Mojo?
  • solumos
    > I started this post out mostly trolling, but the more I've thought about it's not a terrible idea.I feel like this is the unofficial Go motto, and it almost always ends up being a terrible idea.
  • api
    Tangent but... I kinda like the Python language. What I don't like about Python is the way environments are managed.This is something I generally believe, but I think it's particularly important for things like languages and runtimes: the idea of installing things "on" the OS or the system needs to die.Per-workspace or per-package environment the way Go, Rust, etc. does it is correct. Installing packages globally is wrong.There should not be such a thing as "globally." Ideally the global OS should be immutable or nearly so, with the only exception being maybe hardware driver stuff.(Yes I know there's stuff like conda, but that's yet another thing to fix a fundamentally broken paradigm.)
  • avidphantasm
    Now try to call some C++ code from your Go script…
  • flanked-evergl
    Using `uv` with python is significantly safer and better. At least you get null safety. Sure, you can't run at the speed of light, but at least you can have some decent non-halfarsed-retrofitted type checking in your script.
  • assanineass
    [dead]
  • wiseowise
    [flagged]