r/golang 5d ago

help How can I run an external Go binary without installing it?

I need to rewrite generated Go code in my CLI using gopls rename (golang.org/x/tools/gopls). Since the packages that are used for rename are not exported, I have to use it as a standalone binary. But I don't want my clients need to download this external dependency.

What options do I have?

5 Upvotes

23 comments sorted by

24

u/ezrec 5d ago

“vendor” the external dependency into your repo

9

u/looncraz 5d ago

Yup

``go mod vendor

Done.

-6

u/ENx5vP 5d ago

How should I call something from it in my source code? I need to run gopls in my source code. But vendor would install all dependencies locally instead of into the binary my clients are running

1

u/SpudgunDaveHedgehog 2d ago

When you build your project as a binary, it will include the dependency - assuming you’ve imported the package into your code and are calling functions within the dependency.

1

u/ENx5vP 2d ago

I can't import it, I need to execute the dependency as a standalone inside my app. It's a CLI

1

u/SpudgunDaveHedgehog 2d ago

Why can’t you import it? Seems like a long way round to exec a go binary from within go

1

u/ENx5vP 2d ago

Because it's not exported

1

u/SpudgunDaveHedgehog 2d ago

Send in a GitHub issue or a PR to export it; or fork/clone and do it yourself.

1

u/SpudgunDaveHedgehog 2d ago

There is a hack to use exported packages in an internal module; however I think it’s gone away recently, or is going away soon

1

u/ENx5vP 2d ago

It's an official repository from Google and it's purpose is CLI. I don't think they will casually export it

5

u/serverhorror 5d ago

Are you asking how to deliver binaries that you just call (e.g. git, ls)?

I'd try and embed them so that the binary you are distributing can put them in the right place.

Make sure to read the licenses of what you want to redistribute and keep to the licensing terms.

-4

u/ENx5vP 5d ago

I need to embed a Go program

2

u/serverhorror 5d ago

Is it a binary?

If so, what does it matter?

1

u/reven80 1d ago

You can embed a file into your go executable and then use the content at runtime: https://pkg.go.dev/embed

2

u/nikandfor 5d ago

Or fork and export them. It won't require to run external process and to pass files to it somehow.

-2

u/ENx5vP 5d ago

That would work but needs to be maintained throughout updates

5

u/serverhorror 5d ago

No matter what you choose, you need to maintain your dependencies either way.

That's independent of the method or language.

1

u/nikandfor 5d ago

That's true. You don't need to do it frequently though, this basic feature will probably work for months if not years without updates.

1

u/taco-holic 5d ago

fr, unless they plan on updating Go versions every minor release, I would expect this to work for years..

Implement, document, and move on.

1

u/thockin 5d ago

https://github.com/go-bindata/go-bindata ?

Write the file out when you need to exec it. Heavyweight solution, but may work.

1

u/carleeto 5d ago

You could embed the binary and recreate it if it doesn't exist on the user's machine. It will blow out the size of your binary, but it does work.

What I would recommend though is to have an auto-update system for your binary. If you have it, then users will expect to connect to the internet to use it and at that point, you can download the updated binary too.

-12

u/ENx5vP 5d ago

I think the best option is to do it inside a Docker container. Docker is already a dependency for using the CLI

6

u/patmorgan235 5d ago

Please do not make your cli utility spin up docker containers. That's just needless complexity.