go-doudou v2.0.5 New Features Guide
During the 2023 Spring Festival, the open-source Go language microservice framework go-doudou released its first official version of 2023, v2.0.5. This version mainly includes 9 new features. This article will introduce the usage and provide code examples in two parts: the CLI command-line code generator part and the microservice framework part. The code used in this article is available at https://github.com/unionj-cloud/go-doudou-tutorials/tree/master/go-stats and https://github.com/unionj-cloud/go-doudou-tutorials/tree/master/gin2doudou. Please clone the code repository and refer to the example code for understanding.
go-doudou CLI Code Generator
Installation
Since the go-doudou CLI code generator iterates quite quickly, and if there are bugs they will be discovered during command execution and code compilation, without introducing online bugs, it is recommended to always install the main branch version.
go install -v github.com/unionj-cloud/go-doudou/v2@main
1. New Feature: Generate DTO Structs from Database Table Structures
DTO stands for data transfer object, and structs of data structures that need to be transmitted over the network are generally called DTOs. The most common architectural solution for software development now is the layered architecture MVC. V refers to the view layer, and the current and future mainstream implementation solution is still front-end and back-end separation, with the view layer generally developed using front-end SPA frameworks such as Vuejs/Reactjs/Angularjs, etc. M refers to the model layer, including entity classes that map database table structures. C refers to the controller layer, and DTO belongs to this layer. It is not recommended to skip DTO and directly use entity classes in the model layer as data structures for network transmission. Best practice still requires DTO as a medium, with conversion between DTO and entity classes in the control layer code logic to achieve decoupling. This feature can directly map database table structures and generate DTO struct code with a single command, eliminating the manual definition work for developers.
Suppose there are several tables in the tutorial database as shown in the figure below. First, we need to configure the database connection in the .env file.
DB_HOST=localhost
DB_PORT=3306
DB_USER=root
DB_PASSWD=1234
DB_SCHEMA=tutorial
DB_CHARSET=utf8mb4
2
3
4
5
6
Then we execute the following command to generate the DTO.
go-doudou ddl --pre=cad_ -r
--pre
: Specify the table name prefix. In this example, it only generates DTOs for tables with the prefix cad_, optional-r
: Reverse generation, indicating generating Go code from database table structures, required
After executing the command, we can see that the dto
package and entity
package are generated, and the table structure mapping entity classes of the model layer will be generated simultaneously. The
dto
package has a dto_gen.go
file, with the _gen
suffix to distinguish it from manually created files by developers. The "You can edit it as your need" prompt on line 3 indicates that developers can customize and modify this file. Repeated execution of the above command will not overwrite manual modifications by developers, as the code will only be incrementally generated, appended to the end of the file. The go:generate directive on line 11 is followed by the built-in name tool of go-doudou, used for batch modification of struct json tags, defaulting to camelCase with the first letter lowercase. The
CommonComment
struct in the screenshot is the DTO struct corresponding to the cad_common_comment table.
One thing to note is that repeated execution of the above command will decide whether to generate the DTO struct based on whether the entity class mapped to the database table structure in the entity
package exists. That is, if a developer only deletes the dto_gen.go
file or the struct code inside it, without deleting the corresponding entity class in the entity
package, repeated execution of the above command will not regenerate the DTO corresponding to already existing entity classes in the entity
package. If the database table structure is modified and needs to regenerate the DTO, both the corresponding entity class in the entity
package and the corresponding DTO in the dto
package must be deleted as a pair, and then execute the above command.
2. New Feature: Generate Initial go-doudou Project from Swagger2/Swagger3
This feature refers to initializing a go-doudou microservice project through a json file compatible with Swagger 2 or Swagger 3 (OpenAPI 3.0) specifications, mainly including interface definition files, which can facilitate migration from other frameworks to go-doudou, such as from Java ecosystem's Spring Cloud/Spring boot or Go ecosystem's beego framework/gin framework, etc.
Just execute the following command in the same path as the Swagger file.
go-doudou svc init gin2doudou -f gin-admin-swagger.json
gin2doudou
: Specify the project root directory folder name, which is also the default Go module name-f
: Specify the Swagger file path, which can be a relative path, an absolute path, or a download link. This example uses the Swagger file from the well-known open source project https://github.com/LyricTian/gin-admin.
Below is a code screenshot of the generated svc.go
file Click the green triangle button on line 13 to continue generating Protobuf files and gRPC stub code.
Click the green run button on line 12 to continue generating RESTful service code. Execute
go run cmd/main.go
to start the RESTful service.
➜ gin2doudou git:(master) ✗ go run cmd/main.go
2023/01/29 11:03:04 maxprocs: Leaving GOMAXPROCS=16: CPU quota undefined
_ _
| | | |
__ _ ___ ______ __| | ___ _ _ __| | ___ _ _
/ _` | / _ \ |______| / _` | / _ \ | | | | / _` | / _ \ | | | |
| (_| || (_) | | (_| || (_) || |_| || (_| || (_) || |_| |
\__, | \___/ \__,_| \___/ \__,_| \__,_| \___/ \__,_|
__/ |
|___/
2023-01-29 11:03:04 INF ================ Registered Routes ================
2023-01-29 11:03:04 INF +----------------------------+--------+------------------------------+
2023-01-29 11:03:04 INF | NAME | METHOD | PATTERN |
2023-01-29 11:03:04 INF +----------------------------+--------+------------------------------+
2023-01-29 11:03:04 INF | ApiV1Menus | POST | /api/v1/menus |
2023-01-29 11:03:04 INF | ApiV1PubLogin | POST | /api/v1/pub/login |
2023-01-29 11:03:04 INF | ApiV1PubLoginExit | POST | /api/v1/pub/login/exit |
2023-01-29 11:03:04 INF | ApiV1PubRefreshtoken | POST | /api/v1/pub/refreshtoken |
2023-01-29 11:03:04 INF | ApiV1Roles | POST | /api/v1/roles |
2023-01-29 11:03:04 INF | ApiV1Users | POST | /api/v1/users |
2023-01-29 11:03:04 INF | DeleteApiV1Menus_Id | DELETE | /api/v1/menus/:id |
2023-01-29 11:03:04 INF | DeleteApiV1Roles_Id | DELETE | /api/v1/roles/:id |
2023-01-29 11:03:04 INF | DeleteApiV1Users_Id | DELETE | /api/v1/users/:id |
2023-01-29 11:03:04 INF | GetApiV1Menus | GET | /api/v1/menus |
2023-01-29 11:03:04 INF | GetApiV1Menus_Id | GET | /api/v1/menus/:id |
2023-01-29 11:03:04 INF | GetApiV1Menustree | GET | /api/v1/menustree |
2023-01-29 11:03:04 INF | GetApiV1PubCurrentMenutree | GET | /api/v1/pub/current/menutree |
2023-01-29 11:03:04 INF | GetApiV1PubCurrentUser | GET | /api/v1/pub/current/user |
2023-01-29 11:03:04 INF | GetApiV1PubLoginCaptcha | GET | /api/v1/pub/login/captcha |
2023-01-29 11:03:04 INF | GetApiV1PubLoginCaptchaid | GET | /api/v1/pub/login/captchaid |
2023-01-29 11:03:04 INF | GetApiV1Roles | GET | /api/v1/roles |
2023-01-29 11:03:04 INF | GetApiV1Roles_Id | GET | /api/v1/roles/:id |
2023-01-29 11:03:04 INF | GetApiV1Rolesselect | GET | /api/v1/rolesselect |
2023-01-29 11:03:04 INF | GetApiV1Users | GET | /api/v1/users |
2023-01-29 11:03:04 INF | GetApiV1Users_Id | GET | /api/v1/users/:id |
2023-01-29 11:03:04 INF | PutApiV1Menus_Id | PUT | /api/v1/menus/:id |
2023-01-29 11:03:04 INF | PutApiV1PubCurrentPassword | PUT | /api/v1/pub/current/password |
2023-01-29 11:03:04 INF | PutApiV1Roles_Id | PUT | /api/v1/roles/:id |
2023-01-29 11:03:04 INF | PutApiV1Users_Id | PUT | /api/v1/users/:id |
2023-01-29 11:03:04 INF | GetDoc | GET | /go-doudou/doc |
2023-01-29 11:03:04 INF | GetOpenAPI | GET | /go-doudou/openapi.json |
2023-01-29 11:03:04 INF | Prometheus | GET | /go-doudou/prometheus |
2023-01-29 11:03:04 INF | GetConfig | GET | /go-doudou/config |
2023-01-29 11:03:04 INF | GetStatsvizWs | GET | /go-doudou/statsviz/ws |
2023-01-29 11:03:04 INF | GetStatsviz | GET | /go-doudou/statsviz/* |
2023-01-29 11:03:04 INF | GetDebugPprofCmdline | GET | /debug/pprof/cmdline |
2023-01-29 11:03:04 INF | GetDebugPprofProfile | GET | /debug/pprof/profile |
2023-01-29 11:03:04 INF | GetDebugPprofSymbol | GET | /debug/pprof/symbol |
2023-01-29 11:03:04 INF | GetDebugPprofTrace | GET | /debug/pprof/trace |
2023-01-29 11:03:04 INF | GetDebugPprofIndex | GET | /debug/pprof/* |
2023-01-29 11:03:04 INF +----------------------------+--------+------------------------------+
2023-01-29 11:03:04 INF ===================================================
2023-01-29 11:03:04 INF Http server is listening at :6060
2023-01-29 11:03:04 INF Http server started in 3.347258ms
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
Note that if you execute line 12 first, a main function for the RESTful service will be generated. If you execute line 13 first, a main function for the gRPC service will be generated. If a main function already exists, it will be skipped, and go-doudou will not make any modifications. If you want to start both RESTful and gRPC services simultaneously, you need to manually modify the main function. For specific code, please refer to the quick start tutorial on the go-doudou official website.
3. New Feature: Go Language HTTP Client Automatic Gzip Compression for Request Body
The purpose of adding this feature is to compress large-sized request bodies, speed up network transmission, and improve performance. In the go-stats project, execute go-doudou svc http -c
to generate the client package and HTTP client code encapsulating go-resty (unit test files and code need to be implemented by the developer). Gzip-related code is in lines 50-71 of the
client.go
file. Compared to previous versions, there is an additional input parameter of type
Options
, which acts as a switch. The caller can set whether to compress the request body through this switch when calling client methods.
type Options struct {
GzipReqBody bool
}
2
3
4. New Feature: Automatically Generate Enum Type Implementation Methods
go-doudou provides support for enum types, requiring enum types to implement the IEnum
interface:
type IEnum interface {
StringSetter(value string)
StringGetter() string
UnmarshalJSON(bytes []byte) error
MarshalJSON() ([]byte, error)
}
2
3
4
5
6
In previous versions, developers needed to implement this interface manually. With this new feature, code can be generated directly with a single command. As shown in the figure above, you can directly write the
//go:generate
directive shown on line 34 anywhere in the file where the enum type is defined, and then click the green triangle button to execute the command. go-doudou will generate an enums_gen.go
file in the same directory as the original file. In this example, the following code will be generated:
/**
* Generated by go-doudou v2.0.5.
* Don't edit!
*/
package vo
import "encoding/json"
func (k *KeyboardLayout) StringSetter(value string) {
switch value {
case "UNKNOWN":
*k = UNKNOWN
case "QWERTZ":
*k = QWERTZ
case "AZERTY":
*k = AZERTY
case "QWERTY":
*k = QWERTY
default:
*k = UNKNOWN
}
}
func (k *KeyboardLayout) StringGetter() string {
switch *k {
case UNKNOWN:
return "UNKNOWN"
case QWERTZ:
return "QWERTZ"
case AZERTY:
return "AZERTY"
case QWERTY:
return "QWERTY"
default:
return "UNKNOWN"
}
}
func (k *KeyboardLayout) UnmarshalJSON(bytes []byte) error {
var _k string
err := json.Unmarshal(bytes, &_k)
if err != nil {
return err
}
k.StringSetter(_k)
return nil
}
func (k *KeyboardLayout) MarshalJSON() ([]byte, error) {
return json.Marshal(k.StringGetter())
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
5. New Feature: PathVariable Dynamic Route Support
Previous versions did not support PathVariable dynamic routes because query strings could completely replace them in actual development. However, to implement feature 2, this feature was added.
This feature is mainly used when defining service interfaces. You can tell go-doudou which part of the interface method signature needs to be used as a PathVariable to generate routes through an underscore _
followed by uppercase English letters. Let's understand with an example. As shown in line 21 of the code, the method name
GetShelves_ShelfBooks_Book
will generate the interface route /shelves/:shelf/books/:book
, containing two parameters: shelf
and book
. Note: These two parameters must be passed in the method signature, the order doesn't matter, and they can only be all lowercase English letters. In the generated transport/httpsrv/handler.go
file, you can see the following code.
6. New Feature: Generate Go Language HTTP Request Client Code from Swagger2
go-doudou internally calls the https://github.com/getkin/kin-openapi library to handle Swagger2 to Swagger3 conversion.
7. New Feature: Service Definition Support for decimal.Decimal Type
This feature is particularly useful for developing transaction or e-commerce type projects. As shown in the figure above, you can define
decimal.Decimal
type parameters in the service interface definition. The parsing of this type of parameter will be automatically handled in the generated transport/httpsrv/handlerimpl.go
file. The core is calling the
ToDecimalE
method of the cast package.
In the generated Swagger file, decimal.Decimal
parameters or properties are treated as string types, meaning that for front-end colleagues, they are just strings. Example representation of the
DecimalWrapper
struct in Swagger:
type DecimalWrapper struct {
Data decimal.Decimal `json:"data"`
}
2
3
go-doudou Microservice Framework
8. New Feature: Server Automatic Gzip Decompression for HTTP Request Body
A gzipBody
middleware has been added to the framework/rest/middleware.go
file in the go-doudou code repository and has been added to the middleware call chain by default, transparent to developers, and ready to use out of the box. This middleware is only effective for requests with Content-Encoding
equal to gzip
in the HTTP request header.
9. New Feature: Custom Global PanicHandler
The go-doudou framework has added a recovery middleware by default, used to recover the program from panic, transparent to developers, and ready to use out of the box. However, to facilitate custom panic handling, this feature was added. The usage method is shown in the figure below: Just replace the previous version's
rest.NewRestServer()
with rest.NewRestServerWithOptions
and pass in the Functional Options function rest.WithPanicHandler
.