19

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?

Ryota
  • 1,157
  • 2
  • 11
  • 27
  • 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". – Volker Nov 21 '18 at 04:47
  • 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? – Ryota Nov 21 '18 at 08:33
  • 2
    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. – Volker Nov 21 '18 at 09:10
  • 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. – Ryota Nov 21 '18 at 11:06
  • @Volker - 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. – Ryota Nov 22 '18 at 23:04
  • This may be helpful as a reference as go-modules are now fully baked-in : https://go.dev/doc/modules/managing-dependencies#naming_module – avertocle Oct 19 '22 at 12:30

1 Answers1

7

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

Ryota
  • 1,157
  • 2
  • 11
  • 27
  • 1
    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. – Volker Nov 23 '18 at 06:16
  • 2
    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. – Volker Nov 23 '18 at 06:19
  • 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. – Ryota Nov 23 '18 at 09:59