
Installation
go install github.com/ksckaan1/hexago@latest
Dependencies
Make sure that the directory $HOME/go/bin
is appended to the $PATH
ortan variable
Before We Start
If you didn’t hear about hexagonal architecture before, firstly, you could research about it.
Here it is nice blog posts about hexagonal architecture:
What is Hexago?
Hexago is a CLI tool for you to create a go project by applying hexagonal architecture.
Why Hexago?
Hexago can be used to create hexagonal Go projects in an organised way. In this way, you can follow certain standards and have a more manageable application development phase. It imposes its own rules for certain situations and as a result of these impositions, your project gains regularity.
You can also use Hexago only for creating hexagonal projects. It is your preference whether or not to bring it with hexago.
Example Folder Structure
.
├── .hexago/
│ ├── config.yaml
│ └── templates/
├── cmd/
│ └── api/
│ └── main.go
├── config/
├── doc/
├── go.mod
├── internal/
│ ├── domain/
│ │ └── core/
│ │ ├── application/
│ │ │ ├── restapi/
│ │ │ │ └── restapi.go
│ │ │ └── rpcapi/
│ │ │ └── rpcapi.go
│ │ ├── dto/
│ │ │ └── order.go
│ │ ├── model/
│ │ │ └── order.go
│ │ ├── port/
│ │ │ └── order.go
│ │ └── service/
│ │ ├── cancelorder/
│ │ │ └── cancelorder.go
│ │ ├── createorder/
│ │ │ └── createorder.go
│ │ ├── getorder/
│ │ │ └── getorder.go
│ │ ├── listorders/
│ │ │ └── listorders.go
│ │ └── updateorder/
│ │ └── updateorder.go
│ ├── infrastructure/
│ │ ├── cache/
│ │ │ └── cache.go
│ │ └── orderrepository/
│ │ └── orderrepository.go
│ └── pkg/
│ ├── authtoken/
│ │ └── authtoken.go
│ └── uniqueid/
│ └── uniqueid.go
├── pkg/
├── schemas/
└── scripts/
Usage
doctor
The doctor
command displays the status of dependencies that are required for hexago to run properly.
Example:
https://github.com/user-attachments/assets/eebc095e-b806-41b7-bad7-0fb04cd379c7
init
The init
command initialize a Hexago project. This command creates a domain named core
by default. Promts go module name. If leaves blank, uses project folder name as lowercase defaultly.
hexago init <project-path>
Example:
https://github.com/user-attachments/assets/b4ffd97a-a77a-4545-ae3b-41b168f32221
domain
This is the parent command for all domain-related operations.
If the project does not contain any domain, a new service
and app
cannot be created. For this, a domain must be created first.
port
This is the parent command for all port-related operations.
Ports created in domains can be implemented when creating service, app, infrastructure and package. If there is no port in the project, it is not asked which port to implement in the creation screen.
You can create a port manually like bellow.
// internal/domain/<domainname>/port/<portfilename>.go
package port
type ExamplePort interface {
Create(ctx context.Context) error
GetAll(ctx context.Context) ([]string, error)
}
You can use this port when creating a new service, app, infrastructure or package.
service
This is the parent command for all service-related (domain-service) operations.
app
This is the parent command for all application-related (application-service) operations.
Application services are the places where endpoints such as controllers or cli applications are hosted.
infra
This is the parent command for all infrastructure-related operations.
Infrastructures host databases (repositories), cache adapters or APIs that we depend on while writing applications
pkg
This is the parent command for all package-related operations.
Packages are the location where we host features such as utils. There are two types of packages in a hexago project.
-
The first one is located under /internal/pkg
and is not imported by other go developers. Only you use these packages in the project.
-
The second is located under /pkg
. The packages here can be used both by your project and by other go developers.
-
new
This command creates a new package under the internal/pkg/<pkgname>
or /pkg/<pkgname>
directory.
Steps applied when creating a package:
- Insert package name (PascalCase)
- Insert folder name (lowercase)
- Select port which will be implemented (skips this step if there is no port)
- Assert port if selected
- Select package scope (global or internal)
hexago pkg new
https://github.com/user-attachments/assets/1d518553-49ce-4c18-868a-f7ff87829a36
-
ls
This command lists all packages under the internal/pkg
or /pkg
directory.
hexago pkg ls # list internal packages
Flags:
-g
: lists global packages
-a
: list both global and internal packages.
-l
: lists packages line-by-line
https://github.com/user-attachments/assets/6d055ce5-deff-4096-8f8c-00964238cc59
cmd
This is the parent command for all entry point-related (cmd) operations.
Entry points are the places where a go application will start running. entry points are located under the cmd
directory.
run
This command can be used for two different purposes. the run
command create a log file under the logs
directory defaultly.
-
Firstly, if there is an entry point in your project, it can be used to run this entry point.
hexago run <entry-point-name>
https://github.com/user-attachments/assets/3f80bcd9-b737-4f79-8635-ad5a220c7680
Flags:
https://github.com/user-attachments/assets/ef73dfbe-79b3-482b-92d0-dbe0a29738f7
You can customize this run command with given entry point in .hexago/config.yaml
file.
You can specify all envs from config.yaml
file like bellow.
templates: # std | do | <custom>
service: std
application: std
infrastructure: std
package: std
runners:
api: # it runs "go run ./cmd/api", if exists
env:
- ENV_KEY1=ENV_VAL1
- ENV_KEY2=ENV_VAL2
log:
disable: false # write logs to files
seperate_files: true # create log files seperately as api.stderr.log and api.stdout.log
overwrite: true # create new log file when runner called
When the hexago run api
command is executed as above, it starts the api
entry point according to the settings in the config.yaml
file.
-
As a second method, you can use the run
sub-command as an alternative to makefile. You can create a new entry in the runners
section of the .hexago/config.yaml
file to call it with the run
command.
The special commands created do not need to have an entry point equivalent. We can add a special command using the cmd
key.
runners:
custom-command:
cmd: "go version" # overwrite default "go run ./cmd/mycommand/" command
log:
disabled: true # do not print log file
When you run hexago run custom-command
command, you will get the following result.
go version go1.23.0 darwin/arm64