From 7a8ce832e7d1df4084e60f6babeb9b0c184e94c3 Mon Sep 17 00:00:00 2001 From: Hau Nguyen Date: Thu, 8 Dec 2022 16:48:43 +0700 Subject: [PATCH] feat: handle no config viper --- docs/2022-07-10-bootstrap-go.html | 2 +- posts/2022-07-10-bootstrap-go.md | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/2022-07-10-bootstrap-go.html b/docs/2022-07-10-bootstrap-go.html index 700dbfa..179d4c6 100644 --- a/docs/2022-07-10-bootstrap-go.html +++ b/docs/2022-07-10-bootstrap-go.html @@ -71,7 +71,7 @@ import ( )

And then in Makefile:

build:
     go install github.com/golang/protobuf/protoc-gen-go
-

We always get the version of build tools in go.mod each time we install it.
Future contributors will not cry anymore.

Don't use cli libs (spf13/cobra, urfave/cli) just for Go service

What is the point to pass many params (do-it, --abc, --xyz) when what we only need is start service?

In my case, service starts with only config, and config should be read from file or environment like The Twelve Factors guide.

Don't use grpc-ecosystem/grpc-gateway

Just don't.

Use protocolbuffers/protobuf-go, grpc/grpc-go for gRPC.

Write 1 for both gRPC, REST sounds good, but in the end, it is not worth it.

Don't use uber/prototool, use bufbuild/buf

prototool is deprecated, and buf can generate, lint, format as good as prototool.

Use gin-gonic/gin for REST.

Don't use gin.Context when pass context from handler layer to service layer, use gin.Context.Request.Context() instead.

If you want log, just use uber-go/zap

It is fast!

To read config, use spf13/viper

Only init config in main or cmd layer.
Do not use viper.Get... in business layer or inside business layer.

Why?

Don't overuse ORM libs, no need to handle another layer above SQL.

Each ORM libs has each different syntax.
To learn and use those libs correctly is time consuming.
So just stick to plain SQL.
It is easier to debug when something is wrong.

But database/sql has its own limit.
For example, it is hard to get primary key after insert/update.
So may be you want to use ORM for those cases.
I hear that go-gorm/gorm, ent/ent is good.

If you want test, just use stretchr/testify.

It is easy to write a suite test, thanks to testify.
Also, for mocking, there are many options out there.
Pick 1 then sleep peacefully.

If need to mock, choose matryer/moq or golang/mock

The first is easy to use but not powerful as the later.
If you want to make sure mock func is called with correct times, use the later.

Example with matryer/moq:

// Only gen mock if source code file is newer than mock file
+

We always get the version of build tools in go.mod each time we install it.
Future contributors will not cry anymore.

Don't use cli libs (spf13/cobra, urfave/cli) just for Go service

What is the point to pass many params (do-it, --abc, --xyz) when what we only need is start service?

In my case, service starts with only config, and config should be read from file or environment like The Twelve Factors guide.

Don't use grpc-ecosystem/grpc-gateway

Just don't.

Use protocolbuffers/protobuf-go, grpc/grpc-go for gRPC.

Write 1 for both gRPC, REST sounds good, but in the end, it is not worth it.

Don't use uber/prototool, use bufbuild/buf

prototool is deprecated, and buf can generate, lint, format as good as prototool.

Use gin-gonic/gin for REST.

Don't use gin.Context when pass context from handler layer to service layer, use gin.Context.Request.Context() instead.

If you want log, just use uber-go/zap

It is fast!

To read config, use spf13/viper

Only init config in main or cmd layer.
Do not use viper.Get... in business layer or inside business layer.

Why?

Also, be careful if config value is empty.
You should decide to continue or stop the service if there is no config.

Don't overuse ORM libs, no need to handle another layer above SQL.

Each ORM libs has each different syntax.
To learn and use those libs correctly is time consuming.
So just stick to plain SQL.
It is easier to debug when something is wrong.

But database/sql has its own limit.
For example, it is hard to get primary key after insert/update.
So may be you want to use ORM for those cases.
I hear that go-gorm/gorm, ent/ent is good.

If you want test, just use stretchr/testify.

It is easy to write a suite test, thanks to testify.
Also, for mocking, there are many options out there.
Pick 1 then sleep peacefully.

If need to mock, choose matryer/moq or golang/mock

The first is easy to use but not powerful as the later.
If you want to make sure mock func is called with correct times, use the later.

Example with matryer/moq:

// Only gen mock if source code file is newer than mock file
 // https://jonwillia.ms/2019/12/22/conditional-gomock-mockgen
 //go:generate sh -c "test service_mock_generated.go -nt $GOFILE && exit 0; moq -rm -out service_mock_generated.go . Service"
 

Be careful with spf13/cast

Don't cast proto enum:

// Bad
diff --git a/posts/2022-07-10-bootstrap-go.md b/posts/2022-07-10-bootstrap-go.md
index b7fff5d..dd84872 100644
--- a/posts/2022-07-10-bootstrap-go.md
+++ b/posts/2022-07-10-bootstrap-go.md
@@ -206,13 +206,9 @@ Don't use `gin.Context` when pass context from handler layer to service layer, u
 It is fast!
 
 - Don't overuse `func (*Logger) With`. Because if log line is too long, there is a possibility that we can lost it.
-
 - Use `MarshalLogObject` when we need to hide some field of object when log (field is long or has sensitive value)
-
 - Don't use `Panic`. Use `Fatal` for errors when start service to check dependencies. If you really need panic level, use `DPanic`.
-
 - If doubt, use `zap.Any`.
-
 - Use `contextID` or `traceID` in every log lines for easily debug.
 
 ### To read config, use [spf13/viper](https://github.com/spf13/viper)
@@ -225,6 +221,9 @@ Why?
 - Hard to mock and test
 - Put all config in single place for easily tracking
 
+Also, be careful if config value is empty.
+You should decide to continue or stop the service if there is no config.
+
 ### Don't overuse ORM libs, no need to handle another layer above SQL.
 
 Each ORM libs has each different syntax.