go-zero的配置和gorm、自定义返回等的引入以和扩展
工程维度(摘自官网)
.
├── consumer
├── go.mod
├── internal
│ └── model
├── job
├── pkg
├── restful
├── script
└── service
- consumer: 队列消费服务
- internal: 工程内部可访问的公共模块
- job: cron job 服务
- pkg: 工程外部可访问的公共模块
- restful:HTTP 服务目录,下存放以服务为维度的微服务
- script:脚本服务目录,下存放以脚本为维度的服务
- service:gRPC 服务目录,下存放以服务为维度的微服务
服务维度(项目目录)(摘自官网)
example
├── etc
│ └── example.yaml
├── main.go
└── internal
├── config
│ └── config.go
├── handler
│ ├── xxxhandler.go
│ └── xxxhandler.go
├── logic
│ └── xxxlogic.go
├── svc
│ └── servicecontext.go
└── types
└── types.go
- example:单个服务目录,一般是某微服务名称
- etc:静态配置文件目录
- main.go:程序启动入口文件
- internal:单个服务内部文件,其可见范围仅限当前服务
- config:静态配置文件对应的结构体声明目录
- handler:handler 目录,可选,一般 http 服务会有这一层做路由管理,
handler
为固定后缀 - logic:业务目录,所有业务编码文件都存放在这个目录下面,
logic
为固定后缀 - svc:依赖注入目录,所有 logic 层需要用到的依赖都要在这里进行显式注入
- types:结构体存放目录
一、基本配置
1、数据库
1.1、docker-compose.yaml
-
version: '3'
-
services:
-
mysql:
-
container_name: mysql8
-
image: mysql:${MYSQL_VERSION}
-
restart: always
-
ports:
-
- ${MYSQL_PORT}:3306
-
environment:
-
TZ: Asia/Shanghai
-
MYSQL_ROOT_PASSWORD: 123456
-
MYSQL_DATABASE: zero_demo
-
volumes:
-
- ${MYSQL_DIR}/data:/var/lib/mysql
-
- ${MYSQL_DIR}/conf:/etc/mysql/conf.d/
-
- ${MYSQL_DIR}/logs:/logs
-
command:
-
--default-authentication-plugin=mysql_native_password
-
--character-set-server=utf8mb4
-
--collation-server=utf8mb4_general_ci
-
--explicit_defaults_for_timestamp=true
-
--lower_case_table_names=1
-
-
Redis:
-
container_name: redis6
-
image: redis:${REDIS_VERSION}
-
restart: always
-
volumes:
-
- ${REDIS_DIR}/data:/data
-
- ${REDIS_DIR}/conf:/etc/redis/redis.conf
-
ports:
-
- ${REDIS_PORT}:6379
-
command: redis-server /etc/redis/redis.conf
1.2、etc目录下的yaml文件配置
-
Name: demo # 由api中的service名决定
-
Host: 0.0.0.0
-
Port: 8080
-
-
Mysql:
-
DataSource: root:111111@tcp(127.0.0.1:3306)/demo?charset=utf8mb4&parseTime=true&loc=Local
-
-
#jwtAuth go-zero 中内置了 JWT 的解密和验证功能,只需开启jwt使用即可
-
JwtAuth:
-
AccessSecret: demo-aslfhsafsfsflaskfasf
-
AccessExpire: 7200
-
-
#Redis:
-
# Address: 127.0.0.1:6379
-
# Pass: 123456
1.3、internal中的config目录下的config.go文件配置
-
package config
-
-
import "github.com/zeromicro/go-zero/rest"
-
-
//yaml文件中的配置参数经过解析后会解析到此文件中,所以此文件中的参数要与yaml中的参数相对应
-
type Config struct {
-
rest.RestConf
-
Mysql struct {
-
DataSource string
-
}
-
JwtAuth struct {
-
AccessSecret string
-
AccessExpire int64
-
}
-
//Redis struct {
-
// Address string
-
// Pass string
-
//}
-
}
1.4、svc下servicecontext.go文件配置
-
package svc
-
-
import (
-
"demo/common/database"
-
"demo/internal/config"
-
)
-
-
type ServiceContext struct {
-
Config config.Config
-
UserRepo repo.UserRepo
-
//Redis *redis.Redis
-
}
-
-
func NewServiceContext(c config.Config) *ServiceContext {
-
dbConn := database.NewDB(c.Mysql.DataSource) //引入数据库得到数据库链接
-
//newRedis := redis.New(c.Redis.Address, redisConfig(c))
-
return &ServiceContext{
-
Config: c,
-
UserRepo: repo.NewUserRepo(dbConn), //调用数据库(数据库初始化,因为NewServiceContext()函数在main函数中已经调用初始化了)
-
//Redis: newRedis,
-
}
-
}
-
-
//func redisConfig(c config.Config) redis.Option {
-
// return func(r *redis.Redis) {
-
// r.Type = redis.NodeType
-
// r.Pass = c.Redis.Pass
-
// }
-
//}
1.5、引入gorm 链接数据库实现
-
package database
-
-
import (
-
"gorm.io/driver/mysql"
-
"gorm.io/gorm"
-
"gorm.io/gorm/schema"
-
)
-
-
type DBConn struct {
-
ConnGorm *gorm.DB
-
}
-
-
// NewDB 连接并初始化数据库
-
func NewDB(dataSource string) *DBConn {
-
db, err := gorm.Open(mysql.Open(dataSource), &gorm.Config{
-
DisableForeignKeyConstraintWhenMigrating: true,
-
SkipDefaultTransaction: false,
-
NamingStrategy: schema.NamingStrategy{
-
SingularTable: true, // use singular table name, table for `User` would be `user` with this option enabled
-
},
-
})
-
if err != nil {
-
panic("连接数据库失败")
-
}
-
-
d := &DBConn{
-
ConnGorm: db,
-
}
-
InitDB(db)
-
return d
-
}
-
func InitDB(db *gorm.DB) {
-
if err := db.AutoMigrate(
-
&User{},
-
); err != nil {
-
panic(err)
-
}
-
}
1.6、数据库操作业务代码
-
package repo
-
-
import (
-
"demo/common/database"
-
"demo/internal/types"
-
)
-
-
type user struct {
-
db *database.DBConn
-
}
-
-
type UserRepo interface {
-
}
-
-
func NewUserRepo(conn *database.DBConn) UserRepo {
-
return &user{conn}
-
}
2、自定义返回错误--返回数据
格式:code、msg、data标准错误
推荐使用 code-data 统一响应格式用法(官方文档HTTP扩展),此法最简单只需替换即可
2.1、自定义返回错误
在main函数中下面两种引入方式选择其一就行,好处是只需引入一次即可
2.1.1、官方的:
-
package main
-
-
import (
-
"demo/internal/config"
-
"demo/internal/handler"
-
"demo/internal/svc"
-
"flag"
-
"fmt"
-
"github.com/zeromicro/go-zero/core/conf"
-
"github.com/zeromicro/go-zero/core/logc"
-
"github.com/zeromicro/go-zero/rest"
-
)
-
-
var configFile = flag.String("f", "etc/demo.yaml", "the config file")
-
-
func main() {
-
flag.Parse()
-
-
//调试用,调试时使错误以plain(比较直观)的方式打印在终端
-
var x logc.LogConf
-
x.Encoding = "plain"
-
logc.MustSetup(x)
-
-
-
引入自定义返回错误,也可以引入自己构造的
-
/* httpx.SetErrorHandlerCtx(func(ctx context.Context, err error) (int, any) {
-
switch e := err.(type) {
-
case *errors.CodeMsg:
-
return http.StatusOK, xhttp.BaseResponse[types.Nil]{
-
Code: e.Code,
-
Msg: e.Msg,
-
}
-
default:
-
return http.StatusInternalServerError, nil
-
}
-
})*/
-
-
var c config.Config
-
conf.MustLoad(*configFile, &c)
-
-
server := rest.MustNewServer(c.RestConf)
-
defer server.Stop()
-
-
ctx := svc.NewServiceContext(c)
-
handler.RegisterHandlers(server, ctx)
-
-
fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
-
server.Start()
-
}
2.1.2:自定义的
引入代码(写法一):
-
package errorz
-
-
import (
-
"fmt"
-
)
-
-
//**********************************
-
//按go-zero官方例子进行,用 /* */ 标注这段需要配置在main函数中。
-
-
/*
-
httpx.SetErrorHandlerCtx(func(ctx context.Context, err error) (int, any) {
-
switch e := err.(type) {
-
case *errorz.CodeMsg:
-
return http.StatusOK, errorz.CodeMsg[errorz.Nil]{
-
Code: e.Code,
-
Msg: e.Msg,
-
}
-
default:
-
return http.StatusInternalServerError, nil
-
}
-
})*/
-
-
// 用来在main函数中赋值
-
type CodeMsg[T any] struct {
-
Code int `json:"code"`
-
Msg string `json:"msg"`
-
}
-
-
//*****************************************************
-
-
type StdCodeMsg struct {
-
Code int `json:"code"`
-
Msg string `json:"msg"`
-
}
-
-
func (c *StdCodeMsg) Error() string {
-
return fmt.Sprintf("code: %d, msg: %s", c.Code, c.Msg)
-
}
-
-
// New creates a new StdCodeMsg.
-
func NewStdCodeMsg(code int, msg string) error {
-
return &StdCodeMsg{Code: code, Msg: msg}
-
}
-
-
func (c *StdCodeMsg) StdCodeMsg() any {
-
return &StdCodeMsg{
-
Code: c.Code,
-
Msg: c.Msg,
-
}
-
}
-
-
// Nil represents the predeclared value nil.
-
type Nil struct{}
引入代码(写法二):
-
package errorz
-
-
//**********************************
-
//按go-zero官方例子进行,用 /* */ 标注这段需要配置在main函数中用来返回错误。
-
-
/*httpx.SetErrorHandlerCtx(func(ctx context.Context, err error) (int, interface{}) {
-
switch e := err.(type) {
-
case *errorx.BizError:
-
return http.StatusOK, e.Data()
-
default:
-
return http.StatusInternalServerError, nil
-
}
-
})
-
*/
-
-
type CoMsg struct {
-
Code int `json:"code"`
-
Msg string `json:"msg"`
-
}
-
-
type ErrorResponse struct {
-
Code int `json:"code"`
-
Msg string `json:"msg"`
-
}
-
-
func NewCoMsg(code int, msg string) *CoMsg {
-
return &CoMsg{
-
Code: code,
-
Msg: msg,
-
}
-
}
-
-
func (e *CoMsg) Error() string {
-
return e.Msg
-
}
-
-
func (e *CoMsg) Data() any {
-
return &ErrorResponse{
-
e.Code,
-
e.Msg,
-
}
-
}
2.2、自定义返回数据 (最简单的是方式二)
方式一:需要在业务代码的返回函数中调用以下函数
-
// 返回数据---方式一
-
type RespCoMsgSuccess struct {
-
Code int `json:"code"`
-
Message string `json:"message"`
-
Data any `json:"data"`
-
}
-
-
func CoMsgSuccess(data interface{}) *RespCoMsgSuccess {
-
return &RespCoMsgSuccess{200, "OK", data}
-
}
-
-
// 返回数据---方式二
-
type StdResponse[T any] struct {
-
// Code represents the business code, not the http status code.
-
Code int `json:"code" xml:"code"`
-
// Msg represents the business message, if Code = BusinessCodeOK,
-
// and Msg is empty, then the Msg will be set to BusinessMsgOk.
-
Msg string `json:"msg" xml:"msg"`
-
// Data represents the business data.
-
Data T `json:"data,omitempty" xml:"data,omitempty"`
-
}
-
-
func StdSuccess(v any) StdResponse[any] {
-
var resp StdResponse[any]
-
resp.Code = 200
-
resp.Msg = "OK"
-
resp.Data = v
-
return resp
-
}
方式二: code-data 统一响应格式用法(官方文档HTTP扩展)
在 zeromicro 下有一个 x 仓库专门用于对 go-zero 的扩展,其中 HTTP 的扩展支持了:
- code-data 响应格式支持
- xml 响应支持
- code-msg error 类型支持
-
package handler
-
-
import (
-
"net/http"
-
-
"demo/internal/logic"
-
"demo/internal/svc"
-
"demo/internal/types"
-
"github.com/zeromicro/go-zero/rest/httpx"
-
xhttp "github.com/zeromicro/x/http"
-
)
-
-
func loginHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
-
return func(w http.ResponseWriter, r *http.Request) {
-
var req types.LoginRequest
-
if err := httpx.Parse(r, &req); err != nil {
-
// httpx.ErrorCtx(r.Context(), w, err)
-
// code-data 响应格式
-
xhttp.JsonBaseResponseCtx(r.Context(), w, err)
-
return
-
}
-
-
l := logic.NewLoginLogic(r.Context(), svcCtx)
-
resp, err := l.Login(&req)
-
if err != nil {
-
// code-data 响应格式
-
xhttp.JsonBaseResponseCtx(r.Context(), w, err)
-
} else {
-
// code-data 响应格式
-
xhttp.JsonBaseResponseCtx(r.Context(), w, resp)
-
}
-
}
-
}
方式三:官方的定制模板法
可以通过官方的定制模板调用以下方法进行模板生成,也可在自己的返回包中实现,在handler中进行调用
-
//Handler中
-
func GreetHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
-
return func(w http.ResponseWriter, r *http.Request) {
-
var req types.Request
-
if err := httpx.Parse(r, &req); err != nil {
-
httpx.Error(w, err)
-
return
-
}
-
-
l := logic.NewGreetLogic(r.Context(), svcCtx)
-
resp, err := l.Greet(&req)
-
response.Response(w, resp, err)
-
}
-
}
-
package response
-
-
import (
-
"net/http"
-
-
"github.com/zeromicro/go-zero/rest/httpx"
-
)
-
-
type Body struct {
-
Code int `json:"code"`
-
Msg string `json:"msg"`
-
Data interface{} `json:"data,omitempty"`
-
}
-
-
func Response(w http.ResponseWriter, resp interface{}, err error) {
-
var body Body
-
if err != nil {
-
body.Code = -1
-
body.Msg = err.Error()
-
} else {
-
body.Msg = "OK"
-
body.Data = resp
-
}
-
httpx.OkJson(w, body)
-
}
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgbiaba
系列文章
更多
同类精品
更多
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01 -
怎样阻止微信小程序自动打开
PHP中文网 06-13