Hacker News new | ask | show | jobs
by divan 2762 days ago
I really appreciate the work done to help newcomers to answer the question "how to structure Go project propertly", but unless you're building N-th microservice in the company with already established project structures, you don't really need to ask that question.

Every single Go program starts with a simple layout - empty directory and main.go file.

Once you start adding things, you create more .go files in the same folder, and only when it grows bigger you start thinking of moving some abstractions into separate packages.

The key difference with most other languages is that in Go folder means "package", not "namespace for bunch or files". It's a crucial difference that important to keep in mind with Go. And what is (sub)package? When do you need new subpackage? It's just a higher level way to abstract logic or system component - make it more isolated than just concrete type, change the naming and usage API to be more clear and self-sustained.

Before that, you don't have to create new packages (=folders) in Go.

The vast majority of all Go projects will never need `internal` or `cmd` folder, not to mention `pkg` or `web`.

Just start with main.go and let it grow naturally. The simpler and easier your package is, the better.

4 comments

Absolutely. And never group files in a package by type ("models".) A package should have a function ("auth", "health", "reporting", ...)
Thanks for the feedback. The layout used here is not something I came up with. It's an emerged pattern from popular open source projects. Like you said, most probably they all started with simple package and as the project grew abstracted out things finally leading to a similar layout. The layout itself is another community effort (https://github.com/golang-standards/project-layout).

This is not to say that the layout is a standard or the best possible one. It has it's advantages and disadvantages (a whole git repository and a blog article is dedicated to describe both aspects. Hence, I will not get into that discussion here). I chose the layout simply because it's already a well documented one. That being said, I will be more than happy to see other layout and even refactor the structure.

Open source projects generally are not typical web apps or REST API services. They are platforms or tools like docker, kubernetes, Hugo etc. While these projects are good usecases for studying golang code, they feel very complex due to their specific non-simple (if not complex) domain. My idea was to have a web app and API service project which has dead simple domain but highlights the coding practices so that newcomers can read and understand without having to understand what containers are etc.

Few other clarifications I would like to make:

- every directory is not essentially a package in Go. Only directories that have at least one go file are packages. Internal and PKG are not supposed to be packages in that sense. They are just a superficial boundaries between internal and public code.

- web directory is not a package in this project.. it contains static asset files.

- simplicity is something i absolutely love. That is the main reason I like golang. If you look past the outer structure of the project and dig into the code and packages, I think you will see the simplistic design inside. My other projects (e.g. https://github.com/spy16/radium) follow the simplistic method you explained.

When using a single folder structure, how should one go about creating multiple functions with a same name?

I'm creating a web service with Gin, and I have moved each http request handler into its own file. I would like to be able to pass these request handlers to Gin's router with pageA.Handler, pageB.Handler, pageC.Handler, etc, but compiler won't let me because function names have to be unique. Creating unique names for each handler function works fine, but personally it somehow feels messy.

Am I thinking anti-golang way, if I want to namespace these request handlers?

Sort of yes. I have never tried Gin and I actually suggest you to use something else, like gorilla/mux, but that said what you describe sounds like several types implementing an interface...
If you have never tried Gin why suggest to use something else?
Thanks! I didn't know gorilla/mux even existed. I've mostly followed some blog examples in creating my web app, and I guess it shows...
Could you please elaborate more. I always have to scratch my head to really think what should go where. Most of the time I am following MVC paradigm so it dictates about but would like to know more about it.