README ¶
GoMicro Starter Template
This repository serves as a starter template for building microservices in Go. It provides a basic structure and essential components to kickstart the development of a microservice-based application.
Directory Structure
Here is an overview of the directory structure:
Permissions Size User Date Modified Name
drwxrwxrwx - root 1 May 23:01 ./
drwxrwxrwx - root 1 May 22:36 ├── cmd/
drwxrwxrwx - root 1 May 22:36 │ ├── gateway/
.rwxrwxrwx 1.8k root 1 May 22:36 │ │ ├── gateway.go*
.rwxrwxrwx 729 root 1 May 22:36 │ │ ├── headers.go*
.rwxrwxrwx 1.0k root 1 May 22:35 │ │ └── logger.go*
drwxrwxrwx - root 1 May 22:35 │ ├── grpc/
.rwxrwxrwx 1.2k root 1 May 22:35 │ │ ├── grpc.go*
.rwxrwxrwx 1.7k root 1 May 22:35 │ │ └── logger.go*
.rwxrwxrwx 2.0k root 1 May 22:57 │ └── main.go*
drwxrwxrwx - root 1 May 15:19 ├── config/
.rwxrwxrwx 1.7k root 1 May 22:56 │ └── config.go*
.rwxrwxrwx 953 root 1 May 22:50 ├── docker-compose.yml*
.rwxrwxrwx 558 root 1 May 22:41 ├── Dockerfile*
drwxrwxrwx - root 1 May 15:14 ├── docs/
drwxrwxrwx - root 1 May 15:14 │ ├── statik/
.rwxrwxrwx 7.6M root 1 May 15:14 │ │ └── statik.go*
drwxrwxrwx - root 1 May 15:14 │ └── swagger/
.rwxrwxrwx 665 root 1 May 13:42 │ ├── favicon-16x16.png*
.rwxrwxrwx 628 root 1 May 13:42 │ ├── favicon-32x32.png*
.rwxrwxrwx 3.8k root 1 May 15:14 │ ├── gomicro.swagger.json*
.rwxrwxrwx 202 root 1 May 13:42 │ ├── index.css*
.rwxrwxrwx 734 root 1 May 13:42 │ ├── index.html*
.rwxrwxrwx 2.7k root 1 May 13:42 │ ├── oauth2-redirect.html*
.rwxrwxrwx 488 root 1 May 13:42 │ ├── swagger-initializer.js*
.rwxrwxrwx 1.0M root 1 May 13:42 │ ├── swagger-ui-bundle.js*
.rwxrwxrwx 1.5M root 1 May 13:42 │ ├── swagger-ui-bundle.js.map*
.rwxrwxrwx 369k root 1 May 13:42 │ ├── swagger-ui-es-bundle-core.js*
.rwxrwxrwx 1.3M root 1 May 13:42 │ ├── swagger-ui-es-bundle-core.js.map*
.rwxrwxrwx 1.0M root 1 May 13:42 │ ├── swagger-ui-es-bundle.js*
.rwxrwxrwx 1.5M root 1 May 13:42 │ ├── swagger-ui-es-bundle.js.map*
.rwxrwxrwx 323k root 1 May 13:42 │ ├── swagger-ui-standalone-preset.js*
.rwxrwxrwx 518k root 1 May 13:42 │ ├── swagger-ui-standalone-preset.js.map*
.rwxrwxrwx 145k root 1 May 13:42 │ ├── swagger-ui.css*
.rwxrwxrwx 251k root 1 May 13:42 │ ├── swagger-ui.css.map*
.rwxrwxrwx 257k root 1 May 13:42 │ ├── swagger-ui.js*
.rwxrwxrwx 305k root 1 May 13:42 │ └── swagger-ui.js.map*
.rwxrwxrwx 308 root 1 May 23:05 ├── example.env*
.rwxrwxrwx 2.6k root 1 May 19:32 ├── go.mod*
.rwxrwxrwx 194k root 1 May 19:32 ├── go.sum*
drwxrwxrwx - root 1 May 12:35 ├── internal/
drwxrwxrwx - root 1 May 13:55 │ ├── db/
.rwxrwxrwx 1.8k root 1 May 13:55 │ │ ├── db.dbml*
drwxrwxrwx - root 1 May 13:50 │ │ ├── migration/
.rwxrwxrwx 38 root 1 May 12:35 │ │ │ ├── 000001_init_database.down.sql*
.rwxrwxrwx 192 root 1 May 12:35 │ │ │ ├── 000001_init_database.up.sql*
.rwxrwxrwx 33 root 1 May 12:35 │ │ │ ├── 000002_users_table.down.sql*
.rwxrwxrwx 2.6k root 1 May 12:35 │ │ │ └── 000002_users_table.up.sql*
drwxrwxrwx - root 1 May 13:51 │ │ ├── queries/
.rwxrwxrwx 1.7k root 1 May 12:35 │ │ │ └── users.sql*
.rwxrwxrwx 2.6k root 1 May 17:14 │ │ ├── schema.sql*
drwxrwxrwx - root 1 May 13:51 │ │ └── sqlc/
.rwxrwxrwx 597 root 1 May 15:14 │ │ ├── db.go*
.rwxrwxrwx 1.6k root 1 May 15:14 │ │ ├── models.go*
.rwxrwxrwx 1.3k root 1 May 15:14 │ │ ├── querier.go*
.rwxrwxrwx 516 root 1 May 13:50 │ │ ├── querier_extended.go*
.rwxrwxrwx 641 root 1 May 14:50 │ │ ├── store.go*
.rwxrwxrwx 12k root 1 May 15:14 │ │ ├── users.sql_gen.go*
.rwxrwxrwx 2.5k root 1 May 13:49 │ │ └── users_extended.go*
drwxrwxrwx - root 1 May 13:08 │ ├── proto/
drwxrwxrwx - root 1 May 12:29 │ │ ├── google/
drwxrwxrwx - root 1 May 12:29 │ │ │ └── api/
.rwxrwxrwx 1.0k root 1 May 12:29 │ │ │ ├── annotations.proto*
.rwxrwxrwx 3.6k root 1 May 12:29 │ │ │ ├── field_behavior.proto*
.rwxrwxrwx 15k root 1 May 12:29 │ │ │ ├── http.proto*
.rwxrwxrwx 2.7k root 1 May 12:29 │ │ │ └── httpbody.proto*
drwxrwxrwx - root 1 May 12:29 │ │ ├── protoc-gen-openapiv2/
drwxrwxrwx - root 1 May 12:29 │ │ │ └── options/
.rwxrwxrwx 1.8k root 1 May 12:29 │ │ │ ├── annotations.proto*
.rwxrwxrwx 29k root 1 May 12:29 │ │ │ └── openapiv2.proto*
.rwxrwxrwx 900 root 1 May 13:17 │ │ ├── rpc-health.proto*
.rwxrwxrwx 415 root 1 May 13:18 │ │ ├── rpc-welcome.proto*
.rwxrwxrwx 2.4k root 1 May 13:16 │ │ └── service.proto*
drwxrwxrwx - root 1 May 13:59 │ └── service/
.rwxrwxrwx 538 root 1 May 15:08 │ ├── rpc-health.go*
.rwxrwxrwx 499 root 1 May 15:08 │ ├── rpc-welcome.go*
.rwxrwxrwx 842 root 1 May 15:07 │ └── service.go*
.rwxrwxrwx 2.1k root 1 May 22:39 ├── Makefile*
drwxrwxrwx - root 1 May 14:41 ├── pkg/
drwxrwxrwx - root 1 May 12:18 │ ├── crypt/
.rwxrwxrwx 1.5k root 1 May 13:19 │ │ └── hash.go*
drwxrwxrwx - root 1 May 16:18 │ ├── db/
.rwxrwxrwx 1.8k root 1 May 22:55 │ │ ├── connection.go*
.rwxrwxrwx 1.7k root 1 May 16:18 │ │ └── migrate.go*
drwxrwxrwx - root 1 May 14:41 │ ├── email/
.rwxrwxrwx 683 root 1 May 22:53 │ │ ├── email.go*
.rwxrwxrwx 2.1k root 1 May 22:53 │ │ └── gmail.go*
drwxrwxrwx - root 1 May 12:18 │ ├── tokens/
.rwxrwxrwx 340 root 1 May 12:18 │ │ ├── builder.go*
.rwxrwxrwx 277 root 1 May 12:18 │ │ ├── main_test.go*
.rwxrwxrwx 1.2k root 1 May 12:18 │ │ ├── paseto.go*
.rwxrwxrwx 1.8k root 1 May 13:01 │ │ ├── paseto_test.go*
.rwxrwxrwx 1.2k root 1 May 12:18 │ │ └── payload.go*
drwxrwxrwx - root 1 May 12:18 │ ├── utils/
.rwxrwxrwx 319 root 1 May 12:53 │ │ ├── numbers.go*
.rwxrwxrwx 1.9k root 1 May 19:02 │ │ └── randoms.go*
drwxrwxrwx - root 1 May 12:17 │ └── validator/
.rwxrwxrwx 1.9k root 1 May 23:04 │ └── validator.go*
drwxrwxrwx - root 1 May 20:41 ├── public/
.rwxrwxrwx 53k root 1 May 19:52 │ ├── console-log.png*
.rwxrwxrwx 21k root 1 May 19:52 │ ├── evans-grpc.png*
.rwxrwxrwx 30k root 1 May 19:52 │ ├── make-run.png*
.rwxrwxrwx 196k root 1 May 19:52 │ ├── multiple-logs.png*
.rwxrwxrwx 48k root 1 May 19:52 │ ├── postman.png*
.rwxrwxrwx 33k root 1 May 19:52 │ ├── rpc-health.png*
.rwxrwxrwx 24k root 1 May 19:52 │ ├── rpc-welcome.png*
.rwxrwxrwx 236k root 1 May 19:52 │ ├── swagger-playground.png*
.rwxrwxrwx 229k root 1 May 19:52 │ └── swagger.png*
.rwxrwxrwx 34k root 1 May 23:24 ├── README.md*
.rwxrwxrwx 383 root 1 May 13:35 └── sqlc.yaml*
Directory Structure
1. cmd/
-
Size Name - ./ - ├── gateway/ 1.8k │ ├── gateway.go* 729 │ ├── headers.go* 1.0k │ └── mw-logger.go* - ├── grpc/ 1.2k │ ├── grpc.go* 1.7k │ └── mw-logger.go* 2.0k └── main.go*
This directory contains the main executable files for the microservice. It includes the gateway
and grpc
subdirectories.
-
The
gateway
directory houses the implementation for the gateway, which handles HTTP requests and forwards them to the appropriate services.-
gateway/headers.go
file contains utility functions and middleware to handle headers in the microservice. It provides functions to get, and set allow custom headers for incoming and outgoing requests. -
gateway/mw-logger.go
file contains the implementation of a logger middleware specifically designed for thegateway
. It intercepts HTTP requests and logs relevant information such as the request method, URL, and response status. -
Making new middlewares for gateway server is very easy. You have to follow a pattern prefix filename with
mw-
and thenname
. For an examplegateway/mw-name.go
-
-
The
grpc
directory contains the implementation for the gRPC server, which handles communication between microservices using the gRPC protocol.-
grpc/mw-logger.go
file contains the implementation of a logger middleware for thegRPC server
. Similar to the gateway logger, it intercepts incoming gRPC requests and logs relevant information about the request and response. -
Just like gateway middlewares you can create custom middlewares for grpc server. For example
grpc/mw-name.go
-
2. config/
This directory contains configuration files for the microservice. Configuration is an essential part of any application, and here you can define various settings and parameters for your microservice, such as database connections.
-
The
config.go
file contains theConfig
struct and theLoadConfigs
function. -
The
Config
struct represents the application configuration and includes fields forStartTime
,ServiceName
,GrpcPort
,GatewayPort
,Email
, andDatabase
. -
The
LoadConfigs
function is responsible for loading the application configuration from a YAML file. It takes the file path and name as parameters and returns the loaded configuration.
3. docs/
The docs
folder contains documentation-related files for the microservice. Here is an explanation of the files within the docs
folder:
-
statik
folder: This folder contains a generated file namedstatik.go
. Thestatik.go
file is generated using the Statik library and serves as an embedded file system for serving static assets in the microservice. -
swagger
folder: This folder contains the Swagger documentation files for the microservice's API. The Swagger documentation provides a detailed description of the API endpoints, request/response schemas, and other relevant information. The files within this folder include HTML, CSS, JavaScript, and image files used to render the Swagger UI.
4. internal/
The internal/db
folder in the repository contains files related to the database operations of the microservice. Here is an explanation of the files within the internal/db
folder:
-
db.dbml
file: This file represents the database schema using the DBML (Database Markup Language) syntax. It defines the tables, columns, relationships, and other database entities in a human-readable format. -
internal/db/db.dbml
-
The
db.dbml
file is a database schema file that represents the structure of the database using the DBML (Database Markup Language) syntax. DBML is a human-readable language for defining database schemas in a simplified and intuitive way. -
In
db.dbml
file you can find the definition of tables, columns, relationships, and other entities that make up the database schema for the microservice. This file provides a high-level overview of the database structure and serves as a reference for developers and database administrators. -
You can visualize and interact with the
db.dbml
file using tools like dbdiagram.io, which is a popular online platform for designing and documenting database schemas. dbdiagram.io allows you to import thedb.dbml
file and generate interactive diagrams, shareable documentation, and even perform reverse engineering to generate SQL scripts or other database-related artifacts. -
With the help of
db.dbml
we can generateschema.sql
forpostgres
,mysql
andmssql
database
-
-
internal/db/schema.sql
- The
schema.sql
file represents the generated SQL script that defines the database schema. It is created using the dbml2sql command-line interface (CLI) tool, which takes the db.dbml file as input and generates the corresponding SQL statements. - By generating
schema.sql
it becomes easier to write migration files.
- The
-
internal/db/migrations/
-
Size Name - ./ 38 ├── 000001_init_database.down.sql* 192 ├── 000001_init_database.up.sql* 33 ├── 000002_users_table.down.sql* 2.6k └── 000002_users_table.up.sql*
- The migration files are written in SQL and consist of two parts: the "up" migration and the "down" migration. The "up" migration contains the SQL statements to apply the changes and update the schema to a new version, while the "down" migration contains the SQL statements to revert the changes and rollback the schema to a previous version.
-
Writing migrations are much more easier when you already have
schema.sql
generated. -
internal/db/queries/
-
Size Name - ./ 1.7k └── users.sql*
-
The
queries
directory contains raw SQL query files that allow developers to write custom and optimized queries tailored to their application's specific needs. -
To simplify database interaction and enhance productivity, the
sqlc
tool is utilized. It automatically generates Go code based on the SQL queries and database schema, producing type-safe store interfaces. These interfaces provide convenient methods for executing operations on database tables and executing the custom queries defined in thequeries
directory. -
The generated store interfaces ensure compile-time safety and enable developers to write robust code for interacting with the database. The
sqlc
tool supports various databases and generates database-specific code based on the provided queries and schema.
-
-
internal/db/sqlc/
sqlc-
sqlc.yaml
in root directory -
version: '2' sql: - schema: ./internal/db/migration queries: ./internal/db/queries engine: postgresql gen: go: package: sqlc out: ./internal/db/sqlc emit_json_tags: true emit_interface: true emit_empty_slices: true json_tags_case_style: snake emit_prepared_queries: false output_files_suffix: _gen
-
/internal/db/sqlc
-
Size Name - ./ 597 ├── db.go* 1.6k ├── models.go* 1.3k ├── querier.go* 516 ├── querier_extended.go* 641 ├── store.go* 12k ├── users.sql_gen.go* 2.5k └── users_extended.go*
-
The
sqlc
directory contains the generated code produced by the SQLC . SQLC is a code generator that automatically creates Go code based on the SQL queries and the database schema. It utilizes the references from themigrations
andqueries
directories to generate the required code for interacting with the database. -
The generated code includes database models, query executors, and store interfaces, providing type-safe access to the database schema and the custom queries defined in the
queries
directory. This generated code eliminates the need for writing repetitive and error-prone code for database operations. -
By leveraging the
sqlc
directory, developers can perform database operations efficiently and maintain consistency in their codebase. The generated code serves as a reliable bridge between the database schema, custom queries, and the application code, enabling the development of robust and maintainable database-driven applications.
-
-
internal/proto/
a bit of everything-
Size Name - ./ - ├── google/ - │ └── api/ 1.0k │ ├── annotations.proto* 3.6k │ ├── field_behavior.proto* 15k │ ├── http.proto* 2.7k │ └── httpbody.proto* - ├── protoc-gen-openapiv2/ - │ └── options/ 1.8k │ ├── annotations.proto* 29k │ └── openapiv2.proto* 900 ├── rpc-health.proto* 415 ├── rpc-welcome.proto* 2.4k └── service.proto*
-
The
google
directory contains protobuf files used for generating the gateway server. -
The
protoc-gen-openapiv2
directory contains protobuf files with options for generating OpenAPI v2 documentation. -
To create a new API route and an RPC function, you can create a new file in the proto directory with the naming convention rpc-openration-name.proto. This file will define the new RPC operation and its associated request and response message types.
-
Here is how a
rpc-welcome.proto
api looks like -
syntax = "proto3"; package gomicro; // Specify the Go package name for the generated code. option go_package = "github.com/sirjager/rpcs/gomicro"; // WelcomeRequest represents a request for the welcome message. message WelcomeRequest {} // WelcomeResponse represents the response containing the welcome message. message WelcomeResponse { // Message represents the welcome message. string message = 1; }
-
service.proto
-
syntax = "proto3"; package gomicro; import "google/api/annotations.proto"; import "protoc-gen-openapiv2/options/annotations.proto"; import "rpc-welcome.proto"; import "rpc-health.proto"; // Specify the Go package name for the generated gRPC stubs. // The package name determines the import path used in other Go files to reference the generated code. // In this case, the github.com/sirjager/rpcs/gomicro package is used to organize and import the generated gRPC stubs // for the Go Microservice Template. option go_package = "github.com/sirjager/rpcs/gomicro"; // Define OpenAPI v2 options for generating Swagger documentation. option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { info: { title: "Go Microservice Template"; version: "0.1.0"; contact: { name: "SirJager"; url: "https://github.com/sirjager/gomicro"; }; }; }; // Micro service service GoMicro { // Define OpenAPI v2 options for generating tags and external documentation. option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_tag) = { description: "GoMicro is a comprehensive starter template designed to accelerate the development of microservices using the Go programming language. It provides a solid foundation and essential components to expedite the creation of scalable and modular microservice architectures"; external_docs: { url: "https://github.com/sirjager/gomicro"; description: "Find out more about GoMicro"; }; }; // Welcome endpoint returns a welcome message. rpc Welcome(WelcomeRequest) returns (WelcomeResponse) { option (google.api.http) = { get: "/" }; option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { description: "Returns a welcome message"; summary: "Welcome Message"; tags: "System"; }; } // Health endpoint returns the health status of the API. rpc Health(HealthRequest) returns (HealthResponse) { option (google.api.http) = { get: "/v1/health" }; option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { description: "Returns the health status of the API"; summary: "API Health"; tags: "System"; }; } }
-
-
internal/service/
-
- ./ 538 ├── rpc-health.go* 499 ├── rpc-welcome.go* 842 └── service.go*
-
The
service.go
file in theinternal/service
directory contains the implementation of the core service of your application. This file defines a struct namedCoreService
, which represents the main service instance. TheCoreService
struct contains various fields that hold important components for your service.service.go
-
package service import ( "github.com/rs/zerolog" "github.com/sirjager/gomicro/config" "github.com/sirjager/gomicro/internal/db/sqlc" "github.com/sirjager/gomicro/pkg/email" rpc "github.com/sirjager/rpcs/gomicro/go" ) // CoreService represents the core service of your application. type CoreService struct { rpc.UnimplementedGoMicroServer Logr zerolog.Logger // Logger is used for logging. Config config.Config // Config holds the configuration settings. mailer email.MailSender // Mailer is used for sending emails. store sqlc.Store } // NewService creates a new instance of the CoreService. func NewService(logr zerolog.Logger, config config.Config, mailer email.MailSender, store sqlc.Store) (\*CoreService, error) { return &CoreService{ Logr: logr, Config: config, mailer: mailer, store: store, }, nil }
-
Here's a breakdown of the important parts of the service.go
file:
-
CoreService
struct: This struct represents the core service of your application. It implements therpc.UnimplementedGoMicroServer
interface, which is generated from the protobuf service definition. The struct has the following fields: -
Logr
: An instance of thezerolog.Logger
type, which is used for logging purposes. -
Config
: An instance of theconfig.Config
type, which holds the configuration settings for your service. -
mailer
: An instance of theemail.MailSender
type, which is used for sending emails. -
store
: An instance of thesqlc.Store
type, which represents the database store used by your service. -
NewService
function: This function is a constructor for creating a new instance of theCoreService
. It takes in various parameters, such as the logger, configuration, mailer, and store, and returns a pointer to aCoreService
instance. Inside the function, the fields of theCoreService
struct are initialized with the provided values.
The service.go
file is where you can define and implement the core functionalities of your service. You can customize this file to add additional methods and logic to handle the RPC operations defined in the protobuf service.
-
rpc-welcome.go
Here is how we write business logic -
package service import ( "context" "fmt" rpc "github.com/sirjager/rpcs/gomicro/go" ) // welcomeMessage returns a formatted welcome message string. func welcomeMessage(name string) string { return fmt.Sprintf("Welcome to %s Api", name) } // Welcome is a service method that returns a welcome message. func (s *CoreService) Welcome(ctx context.Context, req *rpc.WelcomeRequest) (*rpc.WelcomeResponse, error) { return &rpc.WelcomeResponse{Message: welcomeMessage(s.Config.ServiceName)}, nil }
5. pkg/
- The
pkg
directory contains various packages that provide reusable functionalities for your application. Here's a brief overview of the packages found in thepkg
directory:
Size Name
- ./
- ├── crypt/
1.5k │ └── hash.go*
- ├── db/
1.8k │ ├── connection.go*
1.7k │ └── migrate.go*
- ├── email/
582 │ ├── email.go*
2.3k │ └── gmail.go*
- ├── tokens/
340 │ ├── builder.go*
277 │ ├── main_test.go*
1.2k │ ├── paseto.go*
1.8k │ ├── paseto_test.go*
1.2k │ └── payload.go*
- ├── utils/
319 │ ├── numbers.go*
2.1k │ └── randoms.go*
- └── validator/
1.8k └── validator.go*
-
crypt
: This package contains thehash.go
file, which provides functions for hashing and verifying hashes. -
db
: This package contains theconnection.go
andmigrate.go
files.connection.go
is responsible for establishing connections to the database, whilemigrate.go
handles database migrations, ensuring that the database schema is up to date. -
email
: This package includes theemail.go
andgmail.go
files. It provides functionalities for sending emails. This pkg can be easily extended to use other services likeMailgun
,SendGrid
etc. -
tokens
: Thetokens
package contains files such asbuilder.go
,paseto.go
,paseto_test.go
, andpayload.go
. This package provides utilities for working with authentication and authorization tokens, such as building and parsing tokens using the Paseto token format.I choose to use
paseto
(Platform-Agnostic Security Tokens) instead ofjwt
(JSON Web Token) tokens, Here is why. You can always implement jwt tokens or any other tokens by satisfying builder interface -
utils
: Theutils
package contains files likenumbers.go
andrandoms.go
. This package provides various utility functions related to numbers and randomization likerandom email
.random username
,random password
etc. -
validator
: This package includes thevalidator.go
file, which provides validation functionalities. It contains functions for validating data, such as validatingemail
,username
,uuid
etc. -
These packages in the
pkg
directory are designed to promote code reusability and organization. You can leverage these packages to simplify your application development by utilizing well-defined and tested functionalities in different parts of your codebase.
6. Makefile
The Makefile
is a build automation tool used to define and organize tasks in a project. It provides a convenient way to execute commands for building, testing, and managing various aspects of the project. Let's go through the sections of the provided Makefile
:
-
proto
: This target generates protobuf and gRPC code, Swagger documentation, and static assets. It uses theprotoc
command to compile the.proto
files in the specified directory (PROTO_DIR
) and generates Go code for gRPC, gRPC-gateway, and OpenAPI Swagger. The resulting files are placed in the$(GO_RPC_DIR)
directory. -
tidy
: This target cleans up thego.sum
file and tidies the project dependencies usinggo mod tidy
. It also fetches the latest version of thegithub.com/sirjager/rpcs
package. -
test
: This target runs tests for the project using thego test
command. It includes the-v
flag for verbose output,-cover
flag for code coverage analysis, and-short
flag to skip long-running tests. -
build
: This target builds the project by running thego build
command. It creates an executable namedmain
in the./dist
directory by compiling thecmd/main.go
file. -
run
: This target runs the project using thego run
command. It executes thecmd/main.go
file. -
dbdocs
: This target generates database documentation using thedbdocs
tool. It builds the documentation based on thedb.dbml
file located in./internal/db
directory. -
dbschema
: This target generates the database schema by running thedbml2sql
command. It converts thedb.dbml
file into SQL code and outputs it to the./internal/db/schema.sql
file. -
migratenew
: This target creates a new database migration file using themigrate create
command. It creates a migration file with the given name in the$(DB_MIGRATIONS)
directory. -
migrateup
: This target runs the database migrations (up) using themigrate
command. It applies any pending migrations to the database specified by the$(DB_URL)
. -
migratedown
: This target rolls back the database migrations (down) using themigrate
command. It reverses all applied migrations in the database specified by the$(DB_URL)
. -
sqlc
: This target generates SQL code using SQLC. It runs thesqlc generate
command to generate code based on the SQL queries defined in the project.
These targets can be executed by running make <target>
in the command line, where <target>
is the desired task from the Makefile.
SERVICE_NAME=gomicro
RPCS_DIR=../rpcs
PROTO_DIR=./internal/proto
GO_RPC_DIR=$(RPCS_DIR)/$(SERVICE_NAME)/go
# open api swagger documentations
STATIK_OUT=./docs
SWAGGER_OUT=./docs/swagger
# TEST: database configs
DB_MIGRATIONS=./internal/db/migration
DB_URL=postgres://postgres:password@localhost:5432/databasename?sslmode=disable
7. example.env
config, err := config.LoadConfigs(".", "example")
if err != nil {
logr.Fatal().Err(err).Msg("failed to load configurations")
}
The provided configuration consists of environment variables that can be used to configure a gRPC server, a gateway server, a database connection, and mail SMTP settings. Here's an explanation of each variable:
GRPC_PORT
: The port number on which the gRPC server will listen.
GATEWAY_PORT
: The port number on which the gateway server (e.g., REST server) will listen.
DB_HOST
: The host address of the database server.
DB_PORT
: The port number of the database server.
DB_NAME
: The name of the database to connect to.
DB_USER
: The username to use for authenticating the database connection.
DB_PASS
: The password to use for authenticating the database connection.
DB_DRIVER
: The driver or database type to use for the connection.
DB_ARGS
: Additional arguments or options for the database connection string, such as SSL mode.
DB_MIGRATE
: The path to the database migration files.
For the mail SMTP configuration:
GMAIL_NAME
: The name or display name associated with the Gmail account.
GMAIL_USER
: The email address of the Gmail account.
GMAIL_PASS
: The application-specific password generated for the Gmail account to be used for authentication. You need to get app password for gmail stmp from https://myaccount.google.com/apppasswords
These environment variables can be used to provide the necessary configuration values for the corresponding components of your application, such as the gRPC server, gateway server, database connection, and mail sending functionality.
8. .goreleaser.yaml
config for GoReleaser
- command
make release
orgoreleaser --snapshot --clean
The build configuration for a project named "gomicro" using a build tool GoReleaser. It specifies different builds for multiple operating systems and architectures.
Here's an explanation of the configuration:
project_name: gomicro
: Specifies the name of the project as "gomicro". This is the only thing you will need to change for minimum release configs.
Builds:
id
: An identifier for the build.binary
: Specifies the name of the binary output file. The{{.ProjectName}}
,{{.Os}}
, and{{.Arch}}
are placeholders that will be replaced with actual values during the build process.main
: Specifies the directory path where the main package or entry point of the application is located.goos
: Specifies the target operating system(s) for the build.goarch
: Specifies the target architecture(s) for the build.no_unique_dist_dir
: Indicates whether to use a unique distribution directory for each build. In this case, it is set totrue
, meaning each build will have its own directory.
Archives:
format
: Specifies the format for archiving the build. In this case, it is set to "binary", indicating that the build output will be archived as a binary file.name_template
: Specifies the template for naming the archived file. The{{.ProjectName}}
,{{.Os}}
, and{{.Arch}}
are placeholders that will be replaced with actual values during the build process.
Checksum:
name_template
: Specifies the template for naming the checksum file. The{{.ProjectName}}
is a placeholder that will be replaced with the actual project name during the build process.
This configuration allows you to build the "gomicro" project for different operating systems and architectures, generating binaries and archives with specific naming conventions. It also includes checksum generation for the built files.
9. Dockerfile
- This Dockerfile defines a multi-stage build process to create a container image for a Go application.
- This needs no configuration to work unless you want to modif for your own custom needs.
10. docker-compose.yml
This is a Docker Compose file that defines two services: a PostgreSQL database
service and a gomicro
service.
-
Database Service:
container_name: db
: Sets the container name for the database service as "db".image: postgres:14-alpine
: Specifies the image to use for the database service, which ispostgres:14-alpine
(PostgreSQL 14 with Alpine Linux).volumes: - db:/var/lib/postgresql/data
: Creates a named volume called "db" and mounts it to the/var/lib/postgresql/data
directory inside the database container. This volume is used to persist the database data.environment
: Sets environment variables for the database service, including the username, password, and database name.
-
gomicro Service:
image: ghcr.io/sirjager/gomicro:latest
: Specifies the image to use for thegomicro
service, which isghcr.io/sirjager/gomicro:latest
.container_name: gomicro
: Sets the container name for thegomicro
service as "gomicro".depends_on: - db
: Specifies that thegomicro
service depends on thedb
service. This ensures that the database service starts before thegomicro
service.ports: - 4420 - 4424
: Maps the container's ports 4420 and 4424 to the same ports on the host machine, allowing external access to thegomicro
service.environment
: Sets environment variables for thegomicro
service, including the database connection details, email-related variables, and other configuration variables.entrypoint: ['/app/wait-for.sh', 'db:5432', '--', '/app/start.sh']
: Sets the entrypoint command for thegomicro
container. It first waits for the database service to be available before executing the/app/start.sh
script.command: ['/app/main']
: Specifies the command to run when thegomicro
container starts, which is/app/main
.
This Docker Compose file allows you to run both the database service and the gomicro
service together, with the gomicro
service depending on the database service. The services can communicate with each other, and the gomicro
service is accessible externally through ports 4420 and 4424.
- This Dockerfile defines a multi-stage build process to create a container image for a Go application.
- This needs no configuration to work unless you want to modif for your own custom needs.
11. .github/workflows/release.yml
This is a GitHub Actions workflow that automates the release and deployment process for a Go application. Let's break down the different sections and steps of the workflow:
-
Workflow Configuration: This section defines the name of the workflow and specifies that it should only run when a tag is pushed to the repository. The tags are filtered to match the pattern "v*", which means only tags starting with "v" will trigger the workflow.
-
Environment Variables: This section defines two environment variables -
REGISTRY
andREPOSITORY
.REGISTRY
is set toghcr.io
, which is the GitHub Container Registry.REPOSITORY
is set to the name of the GitHub repository where the workflow is running. -
Jobs: The workflow has a single job called "release" that runs on the latest version of Ubuntu.
-
Permissions: The permissions section specifies that the job needs write access to the repository contents and packages.
-
Steps: a. Checkout Repository: This step checks out the repository code using the
actions/checkout
action. b. Setup Golang: This step sets up the Go environment using theactions/setup-go
action. It specifies the minimum required Go version and enables caching to speed up subsequent builds. c. Create Release: This step uses thegoreleaser/goreleaser-action
action to create a Go release. It invokes thegoreleaser
command with therelease --clean
arguments, which generates a release artifact and publishes it in the repository's release section on GitHub. TheGITHUB_TOKEN
environment variable is passed to authenticate the action. d. Log in to the Container registry: This step uses thedocker/login-action
action to authenticate with the GitHub Container Registry using the providedGITPAT
secret. It uses theghcr.io
registry and sets the username to the actor (user) who triggered the workflow. e. Extract metadata (tags, labels) for Docker: This step uses thedocker/metadata-action
action to extract metadata (such as tags and labels) for the Docker image. It specifies the image to extract metadata from, which is in the formatghcr.io/repository
. f. Build and push Docker image: This step uses thedocker/build-push-action
action to build and push a Docker image. It specifies the build context (the current directory), enables pushing the image, and sets the tags and labels for the image based on the metadata extracted in the previous step.
Overall, this workflow listens for tagged commits, creates a Go release, and deploys the built image to the GitHub Container Registry.