I'm a Go beginner, and I'm trying to create a CLI with Cobra. To bootstrap the project, I used the Cobra Generator, generated a command, a subcommand, and everything works fine.
I now have this type of layout :
cli
├── cmd
│ ├── command.go
│ ├── root.go
│ ├── subcommand.go
├── go.mod
├── go.sum
└── main.go
This doesn't suit me, let's say my project is intended to have lots of commands, or lots of command namespaces, each owned by a different team, it would become very messy and hard to maintain. I would prefer a layout like this :
cli
├── cmd
│ ├── command
│ │ ├── command.go
│ │ └── subcommand.go
│ └── root.go
├── go.mod
├── go.sum
└── main.go
Now, I lack some knowledge about the way packages and imports are done in Go (even after reading the doc here and there), but as far as I understand, a resource can be accessed accross multiple go source files as long as they belong to the same package. But as said in the documentation, "An implementation may require that all source files for a package inhabit the same directory.", so to achieve a layout such as I would like, I would need to have multiple packages, e.g. one for each command namespace, and I think this is fine (or at least, I don't understand what would be wrong with that). So this is what I've tried :
- Create a
command
directory inside thecmd
one - Move the
command.go
file inside thecommand
directory - Change the
package
clause from thecommand.go
file tocommand
- Do the same for
subcommand.go
And this builds fine, but the command is not found(Error: unknown command "command" for "cli"
). I thought it was because I never imported that new command
package, so I imported it in the main.go
file, where the cmd
package is imported.
The build fails, telling me undefined: rootCmd
in the command.go
file. I guess the command
package is unable to see the resources from the cmd
one, so I imported the cmd
package in the command.go
file, and replaced rootCmd
with cmd.rootCmd
(rootCmd
being a variable created in the cli/cmd/root.go
file, part of the Cobra Generator provided files). I really had hope this time, but the result is still the same (undefined: cmd.rootCmd
), and now I'm lost.
Am I trying to do something that is not possible with Cobra?
Am I trying to do something that is possible with Cobra, but not using the Cobra Generator?
Am I trying to do something that should not be done at all (like a bad design from which Go is trying to protect me)?
If not, how should I proceed?