Code Monkey home page Code Monkey logo

lazygo

lazygo框架

快速开始

初始化lazygo项目

方案一:


# 安装lazygo
go install github.com/lazygo/lazygo@latest

# 创建项目 lazygo create 包名 目录名
lazygo create github.com/lazygo/myproject myproject
cd myproject

# 运行
make run

# 构建
make build

方案二:


# 安装lazygo
go install github.com/lazygo/lazygo@latest

# 创建项目目录
mkdir myproject
cd myproject

# 初始化项目 lazygo init 包名
lazygo init github.com/lazygo/myproject

# 运行
make run

# 构建
make build

项目文件目录结构说明

项目初始化后,将会自动创建下列文件目录结构。

.
├── app                              // http请求处理,业务逻辑代码目录
│   ├── controller                   // 控制器
│   │   └── ...
│   ├── middleware                   // 中间件
│   │   └── ...
│   └── request                      // 定义请求和响应
│   │   └── ...
├── config                           // 配置初始化和组件配置注册,可根据需要增减此处代码
│   └── config.go
├── config.toml                      // 配置文件,在config中加载
├── framework                        // 框架相关,通常无需修改
│   ├── app.go                       // 提供Server单例
│   ├── context.go                   // 用户拓展server.Context,在controller和middleware中可以使用拓展Context中提供的方法
│   ├── exception.go                 // 错误处理
│   ├── handler.go                   // 提供一些 HandlerFunc 转换函数
│   └── logger.go                    // 提供日志记录器
├── go.mod
├── main.go
├── Dockerfile
├── Makefile
├── README.md
├── db.sql                           // 项目数据库
├── model                            // model层
│   ├── cache                        // 缓存model
│   │   └── ...
│   ├── db                           // sql数据库model
│   │   └── ...
│   └── model.go
├── pkg                              // 组件包,例如支付sdk组件、云服务sdk组件等
│   └── ...
├── router                           // 路由,需要注册路由后,才能通过http访问服务
│   ├── base.go                      // 基础路由,注册一些全局有效的中间件
│   └── ...                          // 业务路由,可以注册uri到控制器
└── utils                            // 工具
    ├── cache_key.go                 // 缓存key
    ├── define.go                    // 常量
    ├── errors                       // 错误定义
    │   └── errors.go
    └── string.go                    // 字符串处理函数

配置

项目的配置加载相关代码在config/config.go中,可根据实际使用情况修改此文件内容。

lazygo 默认支持toml和json两种格式的配置。

// 加载toml格式的配置
loader := config.Toml(data []byte) (*Config, error)
// 加载json格式的配置
loader := config.Json(data []byte) (*Config, error)

可以调用func (c *Config) Load(field string f any) 方法,将配置信息中的field配置段解析到回调函数f的第一个参数中。 其中回调函数f的定义需符合 func(*CustomStruct) error 或 func([]CustomStruct) error 的形式。 注意需要确保提供的配置内容与回调函数参数结构体类型CustomStruct的数据字段相匹配。如果加载的是json类型的配置,则需要在CustomStruct结构体字段中提供json注解,同理toml格式配置需要提供toml注解。 以下代码为解析配置redis配置段到RedisConfig结构体的示例。

示例:加载json配置

import (
    "github.com/lazygo/lazygo/config"
)

// RedisConfig 可同时增加json和toml注解,便于更换配置文件格式。
type RedisConfig struct {
	Name     string `json:"name" toml:"name"`
	Host     string `json:"host" toml:"host"`
	Port     int    `json:"port" toml:"port"`
	Password string `json:"password" toml:"password"`
	Db       int    `json:"db" toml:"db"`
	Prefix   string `json:"prefix" toml:"prefix"`
}


// 加载json配置
func LoadJsonConfig() {
    jsonConfig := `
    {
        "redis": [
            {
                "name": "redis_1",
                "host": "127.0.0.1",
                "port": 6379,
                "password": "",
                "db": 0
            },
            {
                "name": "redis_2",
                "host": "127.0.0.1",
                "port": 6380,
                "password": "",
                "db": 0
            }
        ],
	"redis": {
             "foo": "bar"
	}
    }
    `

    // 使用json加载器解析配置内容
    jsonLoader, err := config.Json(data)
	if err != nil {
		return err
	}

	// 注册redis配置
	err = jsonLoader.Load("redis", func(conf []RedisConfig) error {
		fmt.Pringln(conf)
	})
	if err != nil {
		return err
	}

}

路由

控制器

控制器的定义

控制器结构体必须包含类型为Context的Ctx成员变量。其定义如下所示:

// UserController 定义一个User控制器
type UserController struct{
	Ctx Context
}

控制器方法的定义规则

控制器的Public类型成员函数用于处理业务逻辑,其入参和出参定义形式必须遵循以下规则。

  • 入参必须有且仅有一个,且此参数必须实现server.Request接口。
  • 返回参数可以有一个或两个,且最后一个返回参数必须时error类型。
  • 当返回仅有1个error类型参数时,如果返回的error为nil框架将不会向HTTP输出任何内容。这可以方便开发者在控制器方法中自行定义HTTP响应的内容。如果返回error不为nil,则根据framework/exception.go中定义的格式输出错误信息到HTTP响应。
  • 当返回有2个参数时,如果返回的第二个参数error为nil,则会根据server.HTTPOKHandler中定义的格式,输出第一个参数到HTTP响应。如果返回error不为nil,处理方式与1个参数时相同,直接向HTTP响应输出错误信息。
// 自定义响应内容的控制器方法
func (c *UserController)Login(request.UserLoginRequest) error {
    ctl.Ctx.HTMLBlob(200, []byte("<h1>lazygo framework</h1>"))
    return nil
}

// 返回一个request.UserProfileResponse结构,框架默认会使用ctx.Succ() 处理返回的*request.UserProfileResponse
// 也就是会将第一个参数*request.UserProfileResponse 整个放入"data"字段中,并序列化成json。{"data": {"name": "李某人"}}
func (c *UserController)Profile(request.UserProfileRequest) (*request.UserProfileResponse, error) {
    resp := &request.UserProfileResponse{
        Name: "李某人",
    }
    return resp, nil
}

// 返回一个map结构,返回结果处理方式同上{"data": {"lazygo": "yes"}}
func (c *UserController)Profile(request.UserProfileRequest) (interface{}, error) {
    resp := map[string]interface{}{
        "lazygo": "yes",
    }
    return resp, nil
}

// 返回一个error信息,返回结果类似 {"errno": 400, "msg": "参数错误"}
// 可在`framework/exception.go`中自行定义返回结果的渲染格式
func (c *UserController)Profile(request.UserProfileRequest) (interface{}, error) {
    return nil, server.NewHTTPError(200, 400, "参数错误")
}

需要注意的是,框架会默认认为所有Public成员函数都是HTTP请求处理函数,也就是说这些Public类型成员函数都必须遵循上述入参和出参的定义规则。在框架启动时会强制检查该控制器下所有的Public成员函数是否满足此规则。如果有不符合此规则的函数,请定义为开头小写的私有类型。 例如(ctl *UserController) Register(req *request.User) (any, error)(ctl *UserController) Login(req *request.User) (any, error)两个函数内部都会调用发送通知的方法,可将发送通知定义为(ctl *UserController)sendMsg(uid uint64, msg string)并在Register和Login中以ctl.sendMsg(uid, msg)的形式调用。

注册控制器到HTTP路由

控制器函数需要注册到路由才能被HTTP请求访问到,注册路由时需要使用server.Controller函数 将控制器函数转换为路由中的HandlerFunc。

// server.Controller 函数定义如下
// 参数h为控制器结构体实例
// method为函数名,若不指定函数名,会自动指定函数名为路由uri最后一个“/”后面的字符串
func Controller(h interface{}, methodName ...string) server.HandlerFunc

注册路由示例代码:

// 将uri /user/profile 注册到UserController.UserInfo
app.Post("/user/profile", server.Controller(controller.UserController{}, "UserInfo"))

// 将uri /user/login 注册到UserController.Login
app.Post("/user/login", server.Controller(controller.UserController{}))

Request 参数绑定和预处理

type ToolsUploadRequest struct {
    Category string      `json:"category" bind:"query,form" process:"trim,cut(20)"`
    Tags     []int       `json:"tag" bind:"query,form"`
    Image    server.File `json:"image"``
}

在框架收到HTTP请求时,请求数据会自动绑定到Request结构体中。绑定需要依赖结构体注解来完成。

  • 对于 Content-Typeapplication/json 的请求,会自动将json数据解析到结构体中。

  • 对于 Content-Typeform-data类型的请求或GET请求,可通过 bind 注解 指定绑定的数据来源。例如 bind:"query,form" 表示优先从url的query参数中获取字段,如果获取不到,则使用form获取。

  • bind支持的类型为:

    valuectx 表示调用context中Value方法获取数据; header 表示从HTTP Header中获取数据; param从路由参数中获取数据; query 从URL Query中获取数据; form 从Post Form中获取数据; file 绑定文件数据。

  • 数据类型为切片时,需要提供的参数格式为 使用逗号分隔的字符串,或json数组字符串。例如?tags=1,2,3?tags=[1,2,3]都可以绑定到[]int类型

在绑定数据时,会自动通过注解中的预处理器函数,对被绑定的参数进行预处理。多个预处理器之间使用逗号隔开。

trim :剔除字符串两端空字符; tolower :字符串转为小写; toupper :字符串转为大写; cut(num int) :如果utf8字符串字符数量超过num个,则将字符串截断。

Request需要实现 func Verify() errorfunc Clear() 两个函数

  • Verify函数在参数绑定后执行,用于对请求参数内容进行校验

  • Clear会在http请求返回响应后执行,用于做一些清理工作

func (r *ToolsUploadRequest) Verify() error {

	if slices.Contains(utils.ImageFormat, path.Ext(r.Image.FileHeader.Filename)) == false {
		return errors.ErrInvalidImageFormat
	}
	return nil
}

func (r *ToolsUploadRequest) Clear() {
	if r.Image.File != nil {
		r.Image.File.Close()
	}
}

中间件

上下文Context

日志

模型

mysql

查询构建器

缓存

错误处理

lazygo's Projects

alist icon alist

🗂️A file list/WebDAV program that supports multiple storages, powered by Gin and Solidjs. / 一个支持多存储的文件列表/WebDAV程序,使用 Gin 和 Solidjs。

easycontrol icon easycontrol

易控,帮助你方便的使用手机远程控制手机。

hero icon hero

A handy, fast and powerful go template engine.

locutus icon locutus

All your standard libraries will be assimilated into our JavaScript collective. Resistance is futile.

mac6 icon mac6

Utility to find IPv6 link-local address from a MAC address

noscreen icon noscreen

这是一个运行在浏览器里的远程桌面应用

pingtunnel icon pingtunnel

Pingtunnel is a tool that send TCP/UDP traffic over ICMP

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.