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")
}
- 启动应用并测试
go run main.go
1.2 基于net/http开发web服务(golang标准库路由注册)
golang标准库已经足以实现简单的web服务,但是使用标准库难以满足我的需求。比如:
- 标准库本身提供了比较简单的路由注册能力,只支持精确匹配,而实际开发时难免会遇到需要使用通配、路径参数的场景
- 标准库暴露给开发者的函数参数是
(w http.ResponseWriter, req *http.Request),这就导致我们需要直接从请求中读取数据、反序列化,响应时手动序列化、设置Content-Type、写响应内容,比较麻烦 - 有时候我们希望能够在不过多地侵入业务的前提下,对请求或响应进行一些前置或后置处理。直接基于标准库开发,业务和非业务代码难免会耦合在一起。
实例:
直接使用标准库开发一个简单的获取当前时间的案例,当客户端以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开发的一般流程可总结为:
- 创建gin.Engine、注册middleware
- 注册路由,编写处理函数,在函数内通过gin.Context获取参数,进行逻辑处理,通过gin.Context暴露的方法(如JSON())写回输出
- 监听端口
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. 目录
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)
}
}