Go Modules - naming convention of directories and packages
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.
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:
Ryota
Updated on October 12, 2020Comments
-
Ryota over 3 years
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
package
s.
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 subdirectoryvalidators/
and keep the same package namepackage 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 topackage 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 inmain.go
? -
Volker over 5 yearsWell, 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 over 5 yearsBut: 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. -
Ryota over 5 yearsHmm, 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.