IM 通信系统 --- 项目介绍及环境搭建

1. 项目简介

1. 核心功能

1. 消息发送与接收

包括: 文字、表情、图片、音频、视频等

2. 聊天模式

  1. 访客模式
  2. 点对点私聊
  3. 群聊(广播)
  4. 机器人

3. 其他功能

  1. 心跳检测下线
  2. 快捷回复
  3. 撤回记录
  4. 拉黑等

2. 技术栈

1. 前端

  1. H5 ajax 获取音频
  2. websocket 发送消息
  3. js/vue 单页面APP

2. 后端

  1. wesocket 组件转发消息
  2. channel && goroutine 提高并发
  3. gin
  4. template
  5. swagger
  6. gorm
  7. logger
  8. govalidator
  9. SQL
  10. NoSQL
  11. MQ

3. 架构图

image-20240915193158357

2. 环境搭建

1. 初始化

go mod init any_chat

2. 下载依赖

go get gorm.io/driver/mysql
go get gorm.io/gorm
go get github.com/gin-gonic/gin
go get gopkg.in/yaml.v2  	# yaml文件读取
go get github.com/sirupsen/logrus     # 日志

3. yaml 配置文件

0. 根配置

gin_any_chat/config/enter.go

package config

type Config struct {
}

1. 环境 配置

gin_any_chat/settings.go

system:
  host: "0.0.0.0"
  port: 8089
  env: release

gin_any_chat/config/system_conf.go

package config

type System struct {
	Host string `yaml:"host"`
	Port int    `yaml:"port"`
	Env  string `yaml:"env"`
}

gin_any_chat/config/enter.go

package config

type Config struct {
	Mysql  Mysql  `yaml:"mysql"`
	Logger Logger `yaml:"logger"`
	System System `yaml:"system"`
}

2. MySQL 配置

gin_any_chat/settings.go

mysql:
  host: 81.70.168.242
  port: 33061
  db: gin_any_chat
  user: root
  password: 123456
  max-idle-conns: 10
  max-open-conns: 100
  log_level: dev
  config: charset=utf8mb4&parse-time=True&loc=Local

gin_any_chat/config/mysql_conf.go

package config

type Mysql struct {
	Host         string `yaml:"host"`
	Port         int    `yaml:"port"`
	Config       string `yaml:"config"` // 高级配置,如 charset 等
	DB           string `yaml:"db"`
	User         string `yaml:"user"`
	Password     string `yaml:"password"`
	MaxIdleConns int    `json:"max-idle-conns" yaml:"max-idle-conns"` // 空闲中的最大连接数
	MaxOpenConns int    `json:"max-open-conns" yaml:"max-open-conns"` // 最大建立连接数
	Charset      string `yaml:"charset"`                              // 编码格式
	ParseTime    string `yaml:"parse-time"`                           // 是否开启时间同步
	Loc          string `yaml:"loc"`                                  // 时间同步为本地时间
	LogLevel     string `yaml:"log_level"`                            // 日志等级,debug就是输出全部SQL,dev,release(线上环境)
}

gin_any_chat/config/enter.go

package config

type Config struct {
    Mysql    Mysql    `yaml:"mysql"`
}

3. 日志 配置

gin_any_chat/settings.go

logger:
  level: info
  prefix: '[blog]'
  director: log
  show_line: true
  log_in_console: true

gin_any_chat/config/logger_conf.go

package config

type Logger struct {
	Level        string `yaml:"level"`
	Prefix       string `yaml:"prefix"`
	Director     string `yaml:"director"`
	ShowLine     bool   `yaml:"show-line"`      // 是否显示行号
	LogInConsole bool   `yaml:"log-in-console"` // 是否显示打印的路径
}

gin_any_chat/config/enter.go

package config

type Config struct {
	Mysql    Mysql    `yaml:"mysql"`
	Logger   Logger   `yaml:"logger"` 
}

gin_any_chat/core/log.go

package core

import (
	"bytes"
	"fmt"
	"gin_any_chat/global"
	"github.com/sirupsen/logrus"
	"os"
	"path"
)

// 日志颜色
const (
	red    = 31
	yellow = 33
	blue   = 36
	gray   = 37
)

type LogFormatter struct{}

func (t *LogFormatter) Format(entry *logrus.Entry) ([]byte, error) {
	// 根据不同的level 显示颜色
	var levelColor int
	switch entry.Level {
	case logrus.DebugLevel, logrus.TraceLevel:
		levelColor = gray
	case logrus.WarnLevel:
		levelColor = yellow
	case logrus.ErrorLevel, logrus.FatalLevel, logrus.PanicLevel:
		levelColor = red
	default:
		levelColor = blue
	}

	var b *bytes.Buffer
	if entry.Buffer != nil {
		b = entry.Buffer
	} else {
		b = &bytes.Buffer{}
	}
	prefix := global.Config.Logger.Prefix
	// 自定义日期格式
	timestamp := entry.Time.Format("2006-01-02 15:04:05")
	if entry.HasCaller() {
		// 自定义文件路径
		funcVal := entry.Caller.Function
		fileVal := fmt.Sprintf("%s:%d", path.Base(entry.Caller.File), entry.Caller.Line)
		// 自定义输出格式
		fmt.Fprintf(b, "%s[%s] \x1b[%dm[%s]\x1b[0m %s %s %s\n", prefix, timestamp, levelColor, entry.Level, fileVal, funcVal, entry.Message)
	} else {
		fmt.Fprintf(b, "%s[%s] \x1b[%dm[%s]\x1b[0m %s\n", prefix, timestamp, levelColor, entry.Level, entry.Message)
	}
	return b.Bytes(), nil
}

func InitLogger() *logrus.Logger {
	mLog := logrus.New()                                // 创建一个实例
	mLog.SetOutput(os.Stdout)                           // 设置输出类型
	mLog.SetReportCaller(global.Config.Logger.ShowLine) // 开启返回函数和行号
	mLog.SetFormatter(&LogFormatter{})                  // 设置自己定义的Formatter
	level, err := logrus.ParseLevel(global.Config.Logger.Level)
	if err != nil {
		level = logrus.InfoLevel
	}
	mLog.SetLevel(level) // 设置最低的Level
	InitDefaultLogger()  // 修改 logrus 全局log样式
	return mLog
}

func InitDefaultLogger() {
	// 修改 logrus 全局log样式
	logrus.SetOutput(os.Stdout)                           // 设置输出类型
	logrus.SetReportCaller(global.Config.Logger.ShowLine) // 开启返回函数和行号
	logrus.SetFormatter(&LogFormatter{})                  // 设置自己定义的Formatter
	level, err := logrus.ParseLevel(global.Config.Logger.Level)
	if err != nil {
		level = logrus.InfoLevel
	}
	logrus.SetLevel(level) // 设置最低的Level
}

gin_any_chat/global/global.go

package global

import (
	"gin_any_chat/config"
)

var (
	Config *config.Config
	Logger *logrus.Logger
)

gin_any_chat/main.go

package main

import (
	"gin_blog/core"
	"gin_blog/global"
)

func main() {
	// 1. 读取配置文件
	core.InitConf()
    
	// 2. 日志配置初始化, 并设置到全局变量
	global.Logger = core.InitLogger()
}

4. Gorm 配置

gin_any_chat/config/mysql_conf.go

package config

import "strconv"

type Mysql struct {
	Host         string `yaml:"host"`
	Port         int    `yaml:"port"`
	Config       string `yaml:"config"` // 高级配置,如 charset 等
	DB           string `yaml:"db"`
	User         string `yaml:"user"`
	Password     string `yaml:"password"`
	MaxIdleConns int    `json:"max-idle-conns" yaml:"max-idle-conns"` // 空闲中的最大连接数
	MaxOpenConns int    `json:"max-open-conns" yaml:"max-open-conns"` // 最大建立连接数
	Charset      string `yaml:"charset"`                              // 编码格式
	ParseTime    string `yaml:"parse-time"`                           // 是否开启时间同步
	Loc          string `yaml:"loc"`                                  // 时间同步为本地时间
	LogLevel     string `yaml:"log_level"`                            // 日志等级,debug就是输出全部SQL,dev,release(线上环境)
}

func (m *Mysql) Dsn() string {
	return m.User + ":" + m.Password + "@tcp(" + m.Host + ":" + strconv.Itoa(m.Port) + ")/" + m.DB + "?" + m.Config
}

gin_any_chat/core/gorm.go

package core

import (
	"fmt"
	"gin_any_chat/global"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"time"
)

func InitGorm() *gorm.DB {
	if global.Config.Mysql.Host == "" {
		global.Logger.Warn("未配置mysql,取消gorm连接")
		return nil
	}
	// 1. 根据配置文件得到连接字符串
	dsn := global.Config.Mysql.Dsn()

	// 2. 设置 MySQL 日志级别和系统环境同步
	var mySQLogger logger.Interface
	if global.Config.System.Env == "debug" {
		// 开发环境显示所有执行的 SQL 语句
		mySQLogger = logger.Default.LogMode(logger.Info)
	} else {
		mySQLogger = logger.Default.LogMode(logger.Error)
	}

	// 3. 建立 MySQL 连接, 并配置
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: mySQLogger,
	})
	if err != nil {
		global.Logger.Error(fmt.Sprintf("[%s] mysql 连接失败", dsn))
		panic(err)
	}

	sqlDB, _ := db.DB()
	sqlDB.SetMaxIdleConns(global.Config.Mysql.MaxIdleConns) // 最大空闲连接数
	sqlDB.SetMaxOpenConns(global.Config.Mysql.MaxOpenConns) // 最多可容纳连接数
	sqlDB.SetConnMaxLifetime(time.Hour * 4)                 // 连接最大服用时间,不能超过mysql的 wait_timeout
	return db
}

gin_any_chat/global/global.go

package global

import (
	"gin_any_chat/config"
	"github.com/sirupsen/logrus"
	"gorm.io/gorm"
)

var (
	Config *config.Config
	Logger *logrus.Logger
	DB     *gorm.DB
)

main.go

package main

import (
	"gin_any_chat/core"
	"gin_any_chat/global"
	"gin_any_chat/routers"
)

func main() {
	// 1. 建立连接, 并配置 编码方式、时区
	//db, err := gorm.Open(mysql.Open("root:123456@tcp(81.70.168.242:33061)/gin_any_chat?charset=utf8mb4&parseTime=True&loc=Local"), &gorm.Config{})
	//if err != nil {
	//	panic("连接数据库发生错误")
	//}

	// 2. 自动迁移模型
	//db.AutoMigrate(&models.UserInfo{})

	// 1. 配置文件初始化
	core.InitConf()

	// 2. 日志配置初始化, 并设置到全局变量
	global.Logger = core.InitLogger()

	// 3. 建立 MySQL 连接, 并设置到全局变量
	global.DB = core.InitGorm()
}

4. 统一响应 配置

1. 自定义状态码

gin_any_chat/models/response/error_code.go

package response

type ErrorCode int

const (
	SETTINGS_ERROR ErrorCode = 5001
)

var (
	ErrorMap = map[ErrorCode]string{
		SETTINGS_ERROR: "系统错误",
	}
)

2. 统一响应函数

gin_any_chat/models/response/response.go

package response

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

const (
	ERROR = iota
	SUCCESS
)

const (
	PANIC_ERROR = "未知错误"
)

type Response struct {
	Code    int    `json:"code"`
	Data    any    `json:"data"`
	Message string `json:"message"`
}

type PageListResponse struct {
	Code    int    `json:"code"`
	Count   int64  `json:"count"`
	Data    any    `json:"data"`
	Message string `json:"message"`
}

// Result 统一返回函数
func Result(code int, data any, msg string, c *gin.Context) {
	c.JSON(http.StatusOK, &Response{
		Code:    code,
		Data:    data,
		Message: msg,
	})
}

// Ok 请求成功返回数据
func Ok(data any, msg string, c *gin.Context) {
	Result(SUCCESS, data, msg, c)
}

// OkWithData 查询数据库成功返回数据
func OkWithData(data any, c *gin.Context) {
	Result(SUCCESS, data, "查询成功", c)
}

// OkWithMessage 请求成功只显示提示信息
func OkWithMessage(msg string, c *gin.Context) {
	Result(SUCCESS, map[string]any{}, msg, c)
}

// Fail 请求失败返回数据
func Fail(data any, msg string, c *gin.Context) {
	Result(ERROR, data, msg, c)
}

// FailWithMessage 请求失败只显示提示信息
func FailWithMessage(msg string, c *gin.Context) {
	Result(ERROR, map[string]any{}, msg, c)
}

// OkWithDataPageList 请求成功返回分页数据
func OkWithDataPageList(count int64, data any, c *gin.Context) {
	c.JSON(http.StatusOK, &PageListResponse{
		Code:    SUCCESS,
		Count:   count,
		Data:    data,
		Message: "请求成功",
	})
}

// FailWithCode 请求失败,根据不同code码显示不同提示信息
func FailWithCode(code ErrorCode, c *gin.Context) {
	msg, ok := ErrorMap[code]
	if !ok {
		Result(ERROR, map[string]any{}, PANIC_ERROR, c)
		return
	}
	Result(int(code), map[string]any{}, msg, c)
}

3. 请求参数校验失败自动返回报错信息

gin_any_chat/utils/valid.go

package utils

import (
	"github.com/go-playground/validator/v10"
	"reflect"
)

// GetValidMsg 根据错误信息中的字段名, 返回结构体中的 msg 错误信息
func GetValidMsg(err error, obj any) string {
	getObj := reflect.TypeOf(obj)
	// 断言 err 是否是 validator.ValidationErrors 类型
	if errs, ok := err.(validator.ValidationErrors); ok {
		for _, e := range errs {
			// 循环每一个错误信息, 根据报错字段名, 获取结构体的具体字段
			if f, exits := getObj.Elem().FieldByName(e.Field()); exits {
				msg := f.Tag.Get("msg")
				return msg
			}
		}
	}

	return err.Error()
}

gin_any_chat/models/response/response.go

// .......

// FailWithError 请求参数校验失败自动返回错误信息
func FailWithError(err error, obj any, c *gin.Context) {
	if err == io.EOF {
		FailWithMessage("参数错误", c)
		return
	}
	msg := utils.GetValidMsg(err, obj)
	FailWithMessage(msg, c)
}

4. 加载错误码到内存

gin_any_chat/modesl/response/error_code.json

{
  "5001": "系统错误"
}

gin_any_chat/core/error_code.go

package core

import (
	"encoding/json"
	"gin_any_chat/global"
	"github.com/sirupsen/logrus"
	"os"
)

const filePath = "models/response/error_code.json"

func ReadErrorCodeFromJson() {
	byteData, err := os.ReadFile(filePath)
	if err != nil {
		logrus.Errorf("读取错误码Json文件错误: %s", err)
		return
	}
	var errMap global.ErrorMap
	err = json.Unmarshal(byteData, &errMap)
	if err != nil {
		logrus.Errorf("Json反序列化到Map错误: %s", err)
		return
	}
	global.ErrorCodes = &errMap
}

global/global.go

package global

import (
	"gin_any_chat/config"
	"gin_any_chat/models/response"
	"github.com/sirupsen/logrus"
	"gorm.io/gorm"
)

type ErrorMap map[response.ErrorCode]string

var (
	Config     *config.Config
	Logger     *logrus.Logger
	DB         *gorm.DB
	ErrorCodes ErrorMap
)

gin_any_chat/main.go

package main

import (
	"gin_any_chat/core"
	"gin_any_chat/global"
	"gin_any_chat/routers"
)

func main() {

	// 1. 配置文件初始化
	core.InitConf()

	// 2.读错误码 JSON 文件到内存中
	core.ReadErrorCodeFromJson()

	// 3. 日志配置初始化, 并设置到全局变量
	global.Logger = core.InitLogger()

	// 4. 建立 MySQL 连接, 并设置到全局变量
	global.DB = core.InitGorm()

	// 5. 根据配置文件, 启动服务器
	router := routers.InitRouter()
	addr := global.Config.System.Addr()
	global.Logger.Infof("项目启动成功,运行在: %s", addr)
	router.Run(addr)
}

5. 初始化配置文件

gin_any_chat/global/global.go

package global

import "gin_blog/config"

var (
	Config *config.Config
)

gin_any_chat/core/conf.go

package core

import (
	"fmt"
	"gin_any_chat/config"
	"gopkg.in/yaml.v3"
	"log"
	"os"
)

func InitConf() {
	const ConfigFile = "settings.yaml"
	c := &config.Config{}
    // 1. 读取文件中的内容
	yamlConf, err := os.ReadFile(ConfigFile)
	if err != nil {
		panic(fmt.Errorf("读取配置文件初失败: %s", err))
	}
    // 2. 将配置文件的内容赋值给 Config 对象
	err = yaml.Unmarshal(yamlConf, c)
	if err != nil {
		log.Fatalf("配置文件初始化失败: %v", err)
	}
	log.Println("配置文件初始化成功!")
    // 3. 将配置文件对象设置到全局变量, 供全局调用
    global.Config = c
}

启动文件调用

gin_any_chat/main.go

package main

import (
	"gin_any_chat/core"
)

func main() {
	// 1. 配置文件初始化
	core.InitConf()
}

6. 路由、API 分包

1. API 分包

gin_any_chat/api/user_api/views.go

package user_api

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

// UserInfoView 响应函数
func (ua UserApi) UserInfoView(c *gin.Context) {
	c.String(http.StatusOK, "ok")
}

gin_any_chat/api/user_api/enter.go

package user_api

type UserApi struct {
}

gin_any_chat/api/enter.go

package api

import "gin_any_chat/api/user_api"

type ApiGroup struct {
	UserApis user_api.UserApi   // 用户相关的所有 API
}

var ApiGroupApp = new(ApiGroup)

2. 路由 分包

gin_any_chat/routers/user_router.go

package routers

import "gin_any_chat/api"

// UserRouters 用户相关的所有路由映射
func (router *RouterGroup) UserRouters() {
	router.GET("/index", api.ApiGroupApp.UserApis.UserInfoView)
}

gin_any_chat/routers/enter.go

package routers

import (
	"github.com/gin-gonic/gin"
)

type RouterGroup struct {
	*gin.RouterGroup
}

// 路由初始化
func InitRouter() *gin.Engine {
    // 1. 设置
    ginMode := global.Config.System.GinMode()
	gin.SetMode(ginMode)
    
	router := gin.Default()
	apiRouterGroup := router.Group("api")  // 添加 /api 路由前缀
	routerGroupApp := &RouterGroup{apiRouterGroup} // 初始化路由分组对象
    
	routerGroupApp.UserRouters()  // 配置所有用户相关的路由映射关系

	return router
}

3. 服务启动

gin_any_chat/config/system_conf.go

package config

import "fmt"

type System struct {
	Host string `yaml:"host"`
	Port int    `yaml:"port"`
	Env  string `yaml:"env"`
}

func (s System) Addr() string {
	return fmt.Sprintf("%s:%d", s.Host, s.Port)
}

func (s System) GinMode() string {
	return fmt.Sprintf("%s", s.Env)
}

gin_any_chat/main.go

package main

import (
	"gin_any_chat/models"
	"gin_any_chat/routers"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

func main() {
    
    // 初始化路由
	routers := routers.InitRouter()
    
    // 服务启动
	routers.Run("127.0.0.1:8848")
}

7. SQL 模型创建及迁移

1. 用户信息表

gin_any_chat/models/UserInfo.go

package models

import "gorm.io/gorm"

type UserInfoModel struct {
	gorm.Model  // 公共字段: ID, CreatedAt, UpdatedAt, DeletedAt
	Name        string
	PassWord    string
	Phone       string
	Email       string
	Identity    string // 用户唯一标识
	ClientIp    string // 用户 IP
	ClientPort  uint16 // 用户 端口
	IsLogout    bool   // 是否下线
	DeviceInfo  string // 用户使用的设备信息
	LoginAt     uint64 // 最近一次上线的时间
	LogoutAt    uint64 // 最近一次离线时间
	HeartbeatAt uint64 // 最近一次心跳时间
}

// TableName 结构体 UserInfo 在数据库中生成的表名
func (u *UserInfoModel) TableName() string {
	return "user_info_model"
}

2. 命令行迁移

gin_any_chat/common/enter.go

package common

import (
	sys_flag "flag"
)

type Option struct {
	Version bool
	DB      bool
}

func Parse() Option {
	db := sys_flag.Bool("db", false, "初始化数据库")
	// 解析命令行参数写入注册的flag中
	sys_flag.Parse()
	return Option{
		//Version: *version,
		DB: *db,
	}

}

// IsWebStop 判断是否需要停止web项目
func IsWebStop(option Option) bool {
	if option.DB {
		return true
	}
	//if option.Version {
	//	return false
	//}
	return false
}

// 根据不用命令执行不同函数
func SwitchOption(option Option) {
	if option.DB {
		MakeMigrations()
	}
	//if option.Version {
	//	Version()
	//}
}

gin_any_chat/common/db.go

package common

import (
	"gin_any_chat/global"
	"gin_any_chat/models"
)

func MakeMigrations() {
	// 1. 提前声明绑定的中间表
	//global.DB.SetupJoinTable(&models.UserInfoModel{}, "CollectsModels", &models.UserCollectModel{})

	// 2. 自动迁移模型, 生成表结构到 MySQL
	err := global.DB.Set("gorm:table_options", "Engine=InnoDB").
		AutoMigrate(
			&models.UserInfoModel{},
		)
	if err != nil {
		global.Logger.Errorf("[ error ] 数据库迁移失败,%s", err.Error())
		return
	}
	global.Logger.Info("[ success ] 数据库迁移成功")

}

gin_any_chat/main.go

package main

import (
	"gin_any_chat/common"
	"gin_any_chat/core"
	"gin_any_chat/global"
	"gin_any_chat/routers"
)

func main() {
	//fmt.Println("main")
	// 1. 配置文件初始化
	core.InitConf()

	// 2.读错误码 JSON 文件到内存中
	core.ReadErrorCodeFromJson()

	//3. 日志配置初始化, 并设置到全局变量
	global.Logger = core.InitLogger()

	// 4. 建立 MySQL 连接, 并设置到全局变量
	global.DB = core.InitGorm()

	// 5. 命令行参数解析
	option := common.Parse()
	// 如果需要停止web项目,就不会执行下面的启动项目
	if common.IsWebStop(option) {
		common.SwitchOption(option)
		return
	}
	common.SwitchOption(option)

	// 6. 根据配置文件, 启动服务器
	router := routers.InitRouter()
	addr := global.Config.System.Addr()
	global.Logger.Infof("项目启动成功,运行在: %s", addr)
	router.Run(addr)
}

3. 执行命令

go run main.go -db

8. 自动生成 API 文档 ( ginSwagger )

1. 环境搭建

1. 安装模块

go get github.com/swaggo/swag/cmd/swag
go get github.com/swaggo/gin-swagger
go get github.com/swaggo/files

2. 配置注释

main.go 中的 mian 函数上方添加注释内容

package main

import (
	"gin_any_chat/common"
	"gin_any_chat/core"
	"gin_any_chat/global"
	"gin_any_chat/routers"
)

// @title IM通信系统 API文档
// @version 1.0
// @description IM通信系统 API文档
// @host 127.0.0.1:8848
// @BasePath /
func main() {
}

3. 初始化生成 API 文档

执行以下命令后, 会自动在项目根目录下生成 docs 文件夹, 其中是 API 文档的 HTML 文件

swag init

2. 使用

1. 引入 docs 目录

main.go

package main

import (
   _ "gin_any_chat/docs"  // 导入 swagger 生成文档目录
)

2. 添加文档访问路由

gin_any_chat/routers/init_router.go

package routers

import (
	swaggerFiles "github.com/swaggo/files"
	gs "github.com/swaggo/gin-swagger"
)

func (router *RouterGroup) InitRoters() {
	router.GET("/swagger/*any", gs.WrapHandler(swaggerFiles.Handler))
}

gin_any_chat/routers/enter.go

package routers

import (
	"gin_any_chat/global"
	"github.com/gin-gonic/gin"
)

type RouterGroup struct {
	*gin.RouterGroup
}

func InitRouter() *gin.Engine {
	ginMode := global.Config.System.GinMode()
	gin.SetMode(ginMode)
	router := gin.Default()

	apiRouterGroup := router.Group("api")
	routerGroupApp := &RouterGroup{apiRouterGroup}
    
	// 配置路由映射关系
	routerGroupApp.UserRouters()
	routerGroupApp.InitRoters()

	return router
}

再次执行命令

swag init

3. 视图添加注释

gin_any_chat/api/user_api/views.go

package user_api

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

// @Tags 首页
// @Summary 首页
// @Description 	描述,可以有多个
// @Param limit query string false  "如果有query参数,则加上,没有则不加,query 表示query查询参数,,false表示没有,true表示必填"
// @Param data query string  false "如果有body参数,则加上,没有则不加,body表示请求体查询参数,false表示没有,true表示必填"
// @Router /api/index [get]   "表示get请求"
// @Produce json
// @Success 200 {object} response.Response{}
func (ua UserApi) UserInfoView(c *gin.Context) {
	c.JSON(http.StatusOK, &gin.H{"message": "OK"})
}

再次执行命令

swag init

**示例: **

1. 创建广告

// AdvertCreateView 创建广告
// @Tags 广告管理
// @Summary 创建广告
// @Description 	描述,可以有多个
// @Param data body AdvertParams  true "表示body的查询参数,false表示没有,true表示必填"
// @Router /api/adverts [post]
// @Produce json
// @Success 200 {object} response.Response{}
func (AdvertApi) AdvertCreateView(c *gin.Context) {}

2. 广告列表

// AdvertListView 广告列表
// @Tags 广告列表
// @Summary 广告列表
// @Description 	描述,可以有多个
// @Param data query models.PageParams  true "如果有body参数,则加上,没有则不加,body表示请求体查询参数,false表示没有,true表示必填"
// @Router /api/adverts [get]   "表示get请求"
// @Produce json
// @Success 200 {object} response.PageListResponse{}
func (AdvertApi) AdvertListView(c *gin.Context) {}

3. 广告更新

// AdvertUpdateView 广告更新
// @Tags 广告管理
// @Summary 广告更新
// @Description 	描述,可以有多个
// @Param data body AdvertParams true "广告参数"
// @Router /api/adverts/:id [put]
// @Produce json
// @Success 200 {object} response.Response{data=string}
func (AdvertApi) AdvertUpdateView(c *gin.Context) {}

4. 广告批量删除

// AdvertRemoveView 广告批量删除
// @Tags 广告管理
// @Summary 广告批量删除
// @Description 	描述,可以有多个
// @Param data body models.RemoveParams true  "广告ID列表"
// @Router /api/adverts [delete]
// @Produce json
// @Success 200 {object} response.Response{data=string}
func (AdvertApi) AdvertRemoveView(c *gin.Context) {}

3. 访问

http://127.0.0.1:8848/api/swagger/index.html
posted @ 2024-09-15 19:24  河图s  阅读(19)  评论(0)    收藏  举报