Gin | 腾讯云开发 CloudBase - AI 原生后端一体化平台
跳到主要内容

Gin

Gin 是一个用 Go 语言编写的 HTTP Web 框架。它具有类似 Martini 的 API,但性能比 Martini 快 40 倍。Gin 使用了自定义版本的 HttpRouter,因此它不仅提供了极快的路由,还提供了中间件支持。

本指南介绍如何在 CloudBase HTTP 云函数上部署 Gin 应用程序。

示例源码请参考: cloudrun-gin

前置条件

在开始之前,请确保您已经:

  • 安装了 Go 1.23 或更高版本
  • 拥有腾讯云账号并创建了云开发环境
  • 了解基本的 Go 语言和 Gin 框架开发知识

第一步:创建 Gin 应用

💡 提示:如果您已经有一个 Gin 应用,可以跳过此步骤。

创建项目目录

mkdir cloudrun-gin
cd cloudrun-gin

初始化 Go 模块

go mod init cloudrun-gin
go get -u github.com/gin-gonic/gin

创建主应用文件

cloudrun-gin 目录下创建 main.go 文件:

package main

import (
"net/http"
"os"

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

func main() {
// 设置 Gin 模式
if os.Getenv("GIN_MODE") == "" {
gin.SetMode(gin.ReleaseMode)
}

router := gin.Default()

// 基础路由
router.GET("/", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "欢迎使用 Gin CloudBase 应用!",
"status": "running",
})
})

// 健康检查
router.GET("/health", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"status": "healthy",
"framework": "Gin",
"go_version": "1.19+",
"gin_version": gin.Version,
})
})

// 获取端口,支持环境变量
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}

// 启动服务器
router.Run(":" + port)
}

本地测试应用

启动应用:

go run main.go

打开浏览器访问 http://localhost:8080,您应该能看到 JSON 响应。

第二步:添加 API 路由

让我们创建一个 RESTful API 来演示 Gin 的功能。

创建用户模型

在项目根目录创建 models 目录,并创建 user.go 文件:

package models

type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}

type ApiResponse struct {
Success bool `json:"success"`
Message string `json:"message"`
Data interface{} `json:"data,omitempty"`
}

创建用户控制器

在项目根目录创建 controllers 目录,并创建 user.go 文件:

package controllers

import (
"net/http"
"strconv"
"sync"

"cloudrun-gin/models"

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

var (
users []models.User
usersMu sync.RWMutex
nextID = 1
)

func init() {
// 初始化测试数据
users = []models.User{
{ID: 1, Name: "张三", Email: "zhangsan@example.com"},
{ID: 2, Name: "李四", Email: "lisi@example.com"},
{ID: 3, Name: "王五", Email: "wangwu@example.com"},
}
nextID = 4
}

// GetUsers 获取用户列表
func GetUsers(c *gin.Context) {
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
limit, _ := strconv.Atoi(c.DefaultQuery("limit", "10"))

usersMu.RLock()
defer usersMu.RUnlock()

startIndex := (page - 1) * limit
endIndex := startIndex + limit

if startIndex >= len(users) {
c.JSON(http.StatusOK, models.ApiResponse{
Success: true,
Message: "获取成功",
Data: []models.User{},
})
return
}

if endIndex > len(users) {
endIndex = len(users)
}

paginatedUsers := users[startIndex:endIndex]

c.JSON(http.StatusOK, models.ApiResponse{
Success: true,
Message: "获取成功",
Data: gin.H{
"total": len(users),
"page": page,
"limit": limit,
"items": paginatedUsers,
},
})
}

// GetUser 根据ID获取用户
func GetUser(c *gin.Context) {
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
c.JSON(http.StatusBadRequest, models.ApiResponse{
Success: false,
Message: "无效的用户ID",
})
return
}

usersMu.RLock()
defer usersMu.RUnlock()

for _, user := range users {
if user.ID == id {
c.JSON(http.StatusOK, models.ApiResponse{
Success: true,
Message: "获取成功",
Data: user,
})
return
}
}

c.JSON(http.StatusNotFound, models.ApiResponse{
Success: false,
Message: "用户不存在",
})
}

// CreateUser 创建用户
func CreateUser(c *gin.Context) {
var newUser models.User
if err := c.ShouldBindJSON(&newUser); err != nil {
c.JSON(http.StatusBadRequest, models.ApiResponse{
Success: false,
Message: "请求参数错误: " + err.Error(),
})
return
}

if newUser.Name == "" || newUser.Email == "" {
c.JSON(http.StatusBadRequest, models.ApiResponse{
Success: false,
Message: "姓名和邮箱不能为空",
})
return
}

usersMu.Lock()
newUser.ID = nextID
nextID++
users = append(users, newUser)
usersMu.Unlock()

c.JSON(http.StatusCreated, models.ApiResponse{
Success: true,
Message: "创建成功",
Data: newUser,
})
}

更新主应用文件