Why use Go-Zero
There can be a third option
- Golang’s community is small, and there are only a handful of microservices frameworks: there are few alternatives to Go-Micro and Go-Kit. Go-zero offers a third possibility.
- Go-micro is not friendly to WebAPI support and requires running micro instructions that are difficult to customize
Startups need a framework to support business growth
What kind of framework do we need? We need a framework to support business growth! In the early stages of product operation, such as requirements verification, we don’t need to adopt a microservices architecture because of the high operational costs. A single app will do. As the business grows and microservices become necessary, we want to be flexible and upgrade without too much code work. That’s where go-Zero is valuable
What is the go – zero
https://github.com/tal-tech/go-zero Go-Zero is a web and RPC framework that integrates various engineering practices. It has the following main features:
- Powerful tool support with as little coding as possible
- Minimal interface
- Fully net/ HTTP compatible
- Support middleware for easy expansion
- A high performance
- Fault – oriented programming, resilient design
- Built-in service discovery and load balancing
- Built – in current limit, fusing, load reduction, and automatic trigger, automatic recovery
- Automatic verification of API parameters
- Timeout cascade control
- Automatic cache control
- Link tracking, statistical alarm, etc
- High concurrent support, stable to ensure the daily flow peak during the epidemic xiao Blackboard
How to use
Before reading this document, upgrade Golang to GO14 or later and enable go Module support. Go14 is only for Gorm support
export GOPROXY=https://goproxy.io,direct
export GO111MODULE=on
Copy the code
Install goctl
Goctl is a code generator for Go-Zero. After all, most of the time writing code is manual work. Download the source code first!
git clone https://github.com/tal-tech/go-zero
cd go-zero/tools/goctl
go build goctl.go
Copy the code
Copy goctl.exe to $gopath/bin
Goctl command description
Browse the document itself. https://github.com/tal-tech/go-zero/blob/master/tools/goctl/goctl.md
The instructions used in this article are as follows
goctl api go -api open.api -dir .
Copy the code
The code is described belowGoctl API go - the open API. API - dir. | | | | | | | generated API go language API specified template file template file name Specify the generated code repository paths The current folderCopy the code
Create a project
Generate the go.mod file
Create the project with the following instructions
mkdir hello
cd hello
go mod init hello
Copy the code
Define the hello. API
The API is designed as follows
describe | format | methods | parameter | return |
---|---|---|---|---|
User registration | /open/register | post | Mobile: mobile phone number,passwd: password,code: image verification code | Id: indicates the user ID. Token: indicates the user token |
The user login | /open/authorization | post | Mobile: mobile phone number,passwd: password,code: image verification code | Id: indicates the user ID. Token: indicates the user token |
Image verification code request | /open/verify | get | Ticket: indicates the ID of the image verification code | Data: Base64 format image |
According to the above description, the template file for writing the API is as follows
type (
UserOptReq struct {
mobile string `json:"mobile"`
passwd string `json:"passwd"`
code string `json:"code"`
}
UserOptResp struct {
id uint `json:"id"`
token string `json:"token"`
}
// Image verification code support
VerifyReq struct {
ticket string `json:"ticket"`
}
// Image verification code support
VerifyResp struct {
data string `json:"data"`}) service open-api {@doc(summary: public API function desc: > Register user registration, authorization user login, verify image verification code interface) @server(handler: registerHandler Folder: open ) post /open/register(UserOptReq) returns(UserOptResp) @server( handler: authorizationHandler folder: open ) post /open/authorization(UserOptReq) returns(UserOptResp) @server( handler: verifyHandler folder: open ) post /open/verify(VerifyReq) returns(VerifyResp) }Copy the code
Pay attention to
- There can only be one service in a file
- The tool will eventually generate various structures using the model in Type as the template, so the parameters should be consistent with the structure
- If we need to manage business by folder, we can define the Folder property
The generated code
Use the following instructions to generate the code
goctl api go -api open.api -dir .
Copy the code
The final code structure is as follows
#tree /F /A
| go.mod
| go.sum
| hello.api
| open.go
|
+---etc
| open-api.yaml
|
\---internal
+---config
| config.go
|
+---handler
| | routes.go
| |
| \---open
| authorizationhandler.go
| registerhandler.go
| verifyhandler.go
|
+---logic
| \---open
| authorizationlogic.go
| registerlogic.go
| verifylogic.go
|
+---svc
| servicecontext.go
|
\---types
types.go
Copy the code
Run the
go run open.go
Copy the code
Test the
The curl http://127.0.0.1:8888/open/register - POST - H X"Content-Type: application/json" -d {\"mobile\":\"15367151352\",\"passwd\":\"testpwd\",\"code\":\"asdf\"}
{"id": 0."token":""}
Copy the code
Integrate star product Gorm V2
Gorm V2 integration has been upgraded to test it
The configuration file
The configuration file is in etc/open-api.yaml
Name: open-API Host: 0.0.0.0 Port: 8888 DataSourceName: root:1D007648b4f8@(127.0.0.1:3306)/gozero? charset=utf8Copy the code
In the/etc/open – API. Yaml DataSourceName add parameters, in the internal/config/config. Add DataSourceName go
type Config struct {
rest.RestConf
DataSourceName string
}
Copy the code
As for the configuration file, the system has some built-in keywords such as Cache, so there is not much information. You can basically configure it any way you want, and then define variables with the same name in your Conf.
Enable Gorm support
Modify the SVC/Servicecontext. go code as follows
package svc
import (
"hello/internal/config"
"hello/internal/models"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/schema"
)
type ServiceContext struct {
Config config.Config
DbEngin *gorm.DB
}
func NewServiceContext(c config.Config) *ServiceContext {
// Enable Gorm support
db, err := gorm.Open(mysql.Open(c.DataSourceName), &gorm.Config{
NamingStrategy: schema.NamingStrategy{
TablePrefix: "tech_".// Table name prefix, 'User' table name should be 't_users'
SingularTable: true.// Use singular table names. In this case, the table name of 'User' should be 't_user'}})// If there is an error, GameOver is used
iferr ! =nil {
panic(err)
}
// Automatically update the table structure, do not create a table
db.AutoMigrate(&models.User{})
return &ServiceContext{Config: c, DbEngin: db}
}
Copy the code
New Model file
Create a new models\models.go file
/ / models \ models go file
package models
import (
"errors"
"hello/internal/utils"
"gorm.io/gorm"
)
type User struct {
gorm.Model
Mobile string `gorm:"index:mobile; type:varchar(13)"`
Passwd string `gorm:"type:varchar(64)"`
}
// Verify that the password is valid before creation
func (u *User) BeforeCreate(db *gorm.DB) error {
if len(u.Passwd) < 6 {
return errors.New("The password is too simple.")}// Encrypt the password for storage
u.Passwd = utils.Password(u.Passwd)
return nil
}
Copy the code
Utils.password is the toolkit we wrote, and the code is as follows
package utils
import (
"fmt"
"golang.org/x/crypto/bcrypt"
)
// Password encryption
func Password(plainpwd string) string {
// Google encrypted package
hash, err := bcrypt.GenerateFromPassword([]byte(plainpwd), bcrypt.DefaultCost) // Encrypt
iferr ! =nil {
fmt.Println(err)
}
encodePWD := string(hash) // The password saved in the database, although each generation is different, only need to save a copy
return encodePWD
}
// Verify the password
func CheckPassword(plainpwd, cryptedpwd string) bool {
err := bcrypt.CompareHashAndPassword([]byte(cryptedpwd), []byte(plainpwd)) // Verify (compare)
return err == nil
}
Copy the code
Implementing business logic
Change the code in logic\open\registerlogic.go as follows
package logic
import (
"context"
"hello/internal/models"
"hello/internal/svc"
"hello/internal/types"
"github.com/tal-tech/go-zero/core/logx"
)
type RegisterLogic struct {
ctx context.Context
logx.Logger
svcCtx *svc.ServiceContext
}
func NewRegisterLogic(ctx context.Context, svcCtx *svc.ServiceContext) RegisterLogic {
return RegisterLogic{
ctx: ctx,
Logger: logx.WithContext(ctx),
svcCtx: svcCtx,
}
}
func (l *RegisterLogic) Register(req types.UserOptReq) (*types.UserOptResp, error) {
user := models.User{
Mobile: req.Mobile,
Passwd: req.Passwd,
}
result := l.svcCtx.DbEngin.Create(&user)
return &types.UserOptResp{
Id: user.ID,
}, result.Error
}
Copy the code
- Add svcCtx *svc.ServiceContext to RegisterLogic because DbEngin is needed
- NewRegisterLogic configuration svcCtx
- Implement the logic in the Register function
result := l.svcCtx.DbEngin.Create(&user)
Test the
> curl http://127.0.0.1:8888/open/register - POST - H X"Content-Type: application/json" -d {\"mobile\":\"15367151352\",\"passwd\":\"testpwd\"}
{"id": 3."token":""}
Copy the code
Look forward to updated feature points
go-zero
The interface definition expects to support multiple Content-Types
UserOptReq struct {
mobile string `json:"mobile" form:"mobile" xml:"mobile"`
passwd string `json:"passwd" form:"passwd" xml:"passwd"`
code string `json:"code" form:"code" xml:"code"`
}
Copy the code
One possible solution is to modify the Parse github.com/tal-tech/go-zero/rest/httpx/requests.go into this model
func Parse(r *http.Request, v interface{}) error {
iferr := ParsePath(r, v); err ! =nil {
return err
}
if strings.Contains(r.Header.Get(ContentType), multipartFormData) {
return ParseForm(r, v)
} else if strings.Contains(r.Header.Get(ContentType), urlencodeformdata) {
return ParseForm(r, v)
} else if strings.Contains(r.Header.Get(ContentType), applicationjson) {
return ParseJsonBody(r, v)
} else {
return errors.New("Unsupported request type")}}Copy the code
Support multiple methods in a file
For example, two methods are generated in the verifyHandler.go file
@server(
handler: verifyHandler
folder: open
)
post /open/verify(VerifyReq) returns(VerifyResp)
post /open/authorization(UserOptReq) returns(UserOptResp)
Copy the code
gorm v2
Suggest the defaultSingularTable
Properties fortrue
NamingStrategy: schema.NamingStrategy{
TablePrefix: "tech_".// Table name prefix, 'User' table name should be 't_users'
SingularTable: true.// Use singular table names. In this case, the table name of 'User' should be 't_user'
},
Copy the code
You are advised to enhance the cache function
It is recommended to support cache such as Redis, memcache, and memory cache
Code acquisition for this article
Follow the public account Betaidea type goZero or gormv2 to obtain
Spread the word
Send benefits to uniAPP users Gospel is coming! After hundreds of thousands of users, our customer service system is finally available. Are you still worried about mall access to customer service? Just one line of code to access!! Just one line of code!!!!
/*kefu.vue*/
<template>
<view>
<IdeaKefu :siteid="siteId" ></IdeaKefu>
</view>
</template>
<script>
import IdeaKefu from "@/components/idea-kefu/idea-kefu.vue"
export default {
components:{
IdeaKefu
},
data() {
return {
siteId:2}}}Copy the code
The effect is great
Address kefu.techidea8.com/html/wiki/ development document