go语言 gin框架学习系列(一):初始化项目

811 阅读4分钟

1.初始化项目

1.1 初始化

1.创建一个项目目录/workspace/go/hello-gin

2.在项目根目录下初始化go.mod文件

go mod init hello-gin

3.安装gin

go get -u github.com/gin-gonic/gin

4.在项目根目录下编写main.go 文件

package main

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

func main() {
    // 1.创建路由
    r := gin.Default()

    // 2.绑定路由规则,执行的函数
    r.GET("/", func(context *gin.Context) {
       context.String(http.StatusOK, "hello,gin")
    })

    // 3.监听端口,默认8080
    r.Run(":8080")
}
  1. 启动应用并测试

go run main.go

image.png

1.2 基于net/http开发web服务(golang标准库路由注册)

golang标准库已经足以实现简单的web服务,但是使用标准库难以满足我的需求。比如:

  1. 标准库本身提供了比较简单的路由注册能力,只支持精确匹配,而实际开发时难免会遇到需要使用通配、路径参数的场景
  2. 标准库暴露给开发者的函数参数是(w http.ResponseWriter, req *http.Request),这就导致我们需要直接从请求中读取数据、反序列化,响应时手动序列化、设置Content-Type、写响应内容,比较麻烦
  3. 有时候我们希望能够在不过多地侵入业务的前提下,对请求或响应进行一些前置或后置处理。直接基于标准库开发,业务和非业务代码难免会耦合在一起。

实例: 直接使用标准库开发一个简单的获取当前时间的案例,当客户端以GET方法请求路径/time时,服务端以json方式返回当前时间,格式为: {"time": "xxx"}.

// 基于net/http开发web服务
func main() {
    http.HandleFunc("/time", func(w http.ResponseWriter, r *http.Request) { // 1.注册路由,指定处理函数
       fmt.Println(w)                                     // 响应对象
       fmt.Println(r)                                     // 请求对象
       w.WriteHeader(http.StatusOK)                       // ret:200  设置响应状态码
       w.Header().Set("Content-Type", "application/json") // 设置响应头
       tim := map[string]string{                          // 构造响应数据
          "time1": time.Now().Format("2006-01-02 15:04:05"),
          "time2": "2023-11-10",
       }
       byts, err := json.Marshal(tim) // Marshal序列化  将go对象序列化程JSON字符串
       if err != nil {
          panic(err)
       }
       w.Write(byts) // 将序列化的JSON字符串写入响应体

    })
    http.ListenAndServe("0.0.0.0: 8000", nil) // 调用http.ListenAndServer进行端口监听
}

总结:基于net/http开发web服务的一般流程:

1.利用http.HandleFunc函数注册路由,指定处理函数。

2.在处理函数内部获取查询参数,路径参数,读取请求体并反序列化。

3.业务逻辑处理

4.错误处理(设置错误响应状态码,错误信息等)

5.调用http.ListenAndServe进行端口监听

其中步骤2.4.5 每个请求都需要写一遍,gin框架在标准库上进行了一些封装。

1.3 基于gin开发的web服务

实例:

func main() {
    // 1.创建路由
    r := gin.Default()

    // 2.绑定路由规则,执行的函数
    r.GET("/", func(c *gin.Context) {

       fmt.Println(c.Query("id")) // 获取参数

       //var user User
       //user1 := c.ShouldBind(&user)  // 使用ShouldBind方法自动绑定请求参数到结构体,并进行校验
       //fmt.Println(user1) // nil 说明绑定成功
       
       c.String(http.StatusOK, "hello,gin") // 响应数据
       a := map[string]string{ // 构造响应数据
          "a": "linjing",
       }
       c.JSON(http.StatusOK, a) // 序列化响应数据
    })

    // 3.监听端口,默认8080
    err := r.Run(":8080") // 8080 监听8080端口
    if err != nil {
       panic(err)
    }
}

基于gin开发的一般流程可总结为:

  1. 创建gin.Engine、注册middleware
  2. 注册路由,编写处理函数,在函数内通过gin.Context获取参数,进行逻辑处理,通过gin.Context暴露的方法(如JSON())写回输出
  3. 监听端口

2.问题总结

问题:在main.go同目录下,新建func1.go文件,在main.go中调用Max1() ,go报错 command-line-arguments undefined

// func1.go
package main

import "fmt"

func Max1() {
    fmt.Println("func1")
}

原因:main 包中的不同的文件的代码不能相互调用,其他包可以,func1.go没有被一起编译执行。

解决方法: 1.在根目录执行go run . 2.执行 go run main.go func1.go 或者 ctrl选中 右键执行

3. 目录

image.png

4.数据库

新建一个表,在model文件夹下创建新的文件 user.go

// /model/user.go
package model

type User struct {
    Id   string `gorm:"type:varchar(100);comment" json:"id"`
    Name string `gorm:"column:name;type:varchar(32);comment:姓名" json:"name" form:"name"`
    Age  int    `gorm:"column:age;type:int(11);comment:年龄" json:"age" `
    Note string `gorm:"column:note;type:varchar(32);comment:备注" json:"note"`
}

在mysql.go 文件中

var (
    MysqlDb                *gorm.DB
    ......
    user                   model.User
)

// 迁移数据表,在没有数据表结构变更时候,建议注释不执行
if mysqlConfig.AutoMigrate == true {
    errs := MysqlDb.AutoMigrate(&projectUser, &dict, &field, &pmProject, &pmPositionAuthor, &userStatus,
       &role, &authorityItem, &PmProjectScheduleDraft, &pmProjectMember, &pmProjectSchedule, &pmMailList,
       &pmProjectUserSite, &pmProjectUserPosition, &pmProjectUserCarType, &nonDisclosureAgreement,
       &vstSecretSignRecord, &pmProjectUserOrg, &pmProjectDraft, &carModelPara, &pmProjectCheckRecord, &pmProjectChange, &releaseNotice, &releaseReadRecord, &user)
    if errs != nil {
       fmt.Println("连接数据库失败,请检查参数:", errs)
       os.Exit(1)
    }
}