Hacker News new | ask | show | jobs
by ballresin 867 days ago
What is the value making main.go as small as possible?

Whose dreams come true in this scenario?

10 comments

The author goes on to explain a few scenarios where the pattern is helpful. It's not to keep main.go as small as possible, it's so that you can test parts of your main.go file properly. In my experience, if all of my logic is stuffed into `func main() {}`, then I can't actually test it. If I have a helper method(like run in this case), I can test out specific scenarios and ensure the application handles it properly. Some of the examples Mat gave were handling context cancellations properly.
“Whose dreams come true in this scenario?”

I love this! I will use this as well.

There are so many situations where I have a feeling that people are solving problems that don’t exist. In code I run into at work, code and projects I see online, etc

The “whose dreams are you making come true” really applies here, because dreams are exactly what they are.

I spent quite some time writing an automatic image resizer and optimiser for my blog. Does it matter? No! Should I have spent that time writing blog posts instead? Yes! Still I was chasing some dream.

Thanks for this image

If you do, you can use the application as a library and most of your code will also be easier to test.
I've never been a fan of making main.go one line. I create the logger, parse the flags, create objects from the flags, and call Run() or something. In the tests, you aren't ever going to do those things in the same way, so there is really no point in putting them in some other file.
Usually your main function can't be used by any other part of your program. You should move all component implementations to modules so they can be re-used elsewhere.
For bespoke internal services, I like to keep main.go as flat as reasonable, like a "script". Handlers can have their own files but the bulk of the control flow and moving parts should be apparent from reading the main file.

Abstracting things away from main makes it less readable and is general pointless for bespoke services that will be deployed in exactly one configuration.

That's a nice way of putting it. When exploring a new codebase for the first time it can be very helpful to have main.go give you a high level idea about the overall structure of the program.
not main.go but func main. This allows your run function to return an error and you only need to deal with the abruptness of using os.Exit once
The initialization has to be done in a separate function that you call from the setup code for your end-to-end tests.
I assume you mean main() and not main.go.

main() is the only place where you can't return an error. In order to keep as much of the code as idiomatic as possible you just call something like run() where you can do so.

In addition there is the testing aspect. You can't invoke main() from your tests.

The idea is to keep the untestable code as small as possible but in practice you just add a layer of indirection and all of your untestable init code is in a different castle.