Go Modules - naming convention of directories and packages
Asked Answered
S

1

25

I understand Go Modules are yet an experimental opt-in feature, and perhaps because of that, I cannot find clear guidance on how to name directories and packages.
In these Package names in Go Blog post and Package name in Effective Go, they talk about that the directory should match the package name - but I wasn't certain if Go Modules would follow the same pattern.

If I want to bundle my business logic in package business with many files, is it reasonable to create subdirectory validators/ and keep the same package name package business?

someDir
├── business
│   ├── businessA.go // package business
│   ├── businessB.go // package business
│   ├── businessC.go // package business
│   └── validators
│       ├── businessValidatorX.go // package business, or validators?
│       ├── businessValidatorY.go // package business, or validators?
│       └── businessValidatorZ.go // package business, or validators?
├── go.mod   // module example.com
└── main.go

Approach 1.

If I were to go with the same package name:

// main.go
package main

import (
        "example.com/business"
        "example.com/business/validators"
)

// both imports would be combined to the same `business` package?
func main() {
        b := business.SomeLogic()
        business.ValidateX(b) // validator from the same package
}

This looks to be prone to export conflict - but it is simple.

Approach 2.

If the validators/ path maps to package validators, the consuming code would look like the below instead.

// main.go
package main

import (
        "example.com/business"
        "example.com/business/validators"
)

func main() {
        b := business.SomeLogic()
        validators.ValidateX(b) // validator from a separate package
}

How should I manage a package consisted of many files? Is the Approach 1. reasonable, although it somewhat contradicts from the blog post and doc above?
Or should I go with Approach 2., complying with the convention, and add an alias as necessary in main.go?

Salon answered 21/11, 2018 at 1:40 Comment(6)
Nothing in regard to naming packages has changed with the introduction of modules. Your idea of approach 1 is totally wrong and does not work: Packages cannot be "combined".Rhetic
Thanks for the input, but defining a single package with multiple files should be conventional (how there are businessA/B/C to orchestrate package business). Approach A was merely to structure files using extra subdirectory. Does that mean I’m better off putting all files in a single directory and not have subdirectory at all, if I were to achieve something along the line with Approach 1?Salon
You have to read How to Write Go Code. There is one and only one way to write Go code. A package is one folder and may contain one or more source code files. Approach 1 is 100% undoabe in Go. Forget about that now and forever. It is one folder == one package. And there is no opinion or desire to have here.Rhetic
Thanks for the clear answer, it seemed as if the Go Module introduced slight flexibility with it, but clearly I was reading it wrong. May I shamelessly ask - would you mind posting it as an answer, so that I can close this question? With the Go Modules in picture, I had difficulty finding the right doc, and this may still be useful for newbies like myself.Salon
@Rhetic - I played a bit more and posted an answer with some information along the line with your comment. It may be an over-complication, but I find having a clear answer with some reference helps, if by any chance someone ends up finding this post. Thanks for your input anyways.Salon
This may be helpful as a reference as go-modules are now fully baked-in : go.dev/doc/modules/managing-dependencies#naming_moduleUnbowed
S
10

Approach 2 is correct.

Being a Go newbie, I had mistakenly thought that Approach 1 was one possible way, as Go does allow having package name different from directory name.

As Volker helped in the comments, Approach 1 is definitely not possible.
You will get a straight compilation error when trying to combine packages.

compilation error

The introduction of Go Modules does not affect the best practices outlined in existing documents, such as:

As a side note, I also came to know that package name should be singular form.

So that would leave me with the following structure along with Approach 2:

structure following the convention

Salon answered 22/11, 2018 at 22:59 Comment(3)
Well, I have to disappoint you. This answer is technically not correct as approach 1 is possible. You see, I lied in my comment above. Nevertheless my advice and your conclusion are 100% valid. There is just one golden way to structure your code layout and build your packages and projects. This is explained in How to Write Go Code and perfectly illustrated by the stdlib and the rest of the supporting Go repos and everybody should follow this advice and nothing else.Rhetic
But: It is technically not true. Instead of building your code with the go tool one can invoke the compiler and linker manually (or typically through a makefile or some other build tooling) and this allows to combine arbitrary files into one package. Nobody sane does this ever as this break each and every Go tool in the world, but it is possible and it is done.Rhetic
Hmm, that is an eyeopening point. As I find Go having golden rules and being opinionated how things should be done, I appreciate how the community can heavily rely on the conventions, more so than other languages IMO. Working around the go tools is probably beyond the scope of the original question, but certainly a valid point.Salon

© 2022 - 2024 — McMap. All rights reserved.