0、参考文章:http://www.haijin.xyz/article/629
1、入门:
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
r.GET("/hi", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "gin",
})
c.Header("site","haijin")
})
r.Run(":8068")
}
package main
import "github.com/gin-gonic/gin"
func main() {
router := gin.Default()
v1 := router.Group("/v1")
{
v1.POST("/login", login)
v1.POST("/submit", submit)
v1.POST("/read", read)
}
v2 := router.Group("/v2")
{
v2.POST("/login", login)
v2.POST("/submit", submit)
v2.POST("/read", read)
}
router.Run(":8080")
}
func login(c *gin.Context) {
}
func submit(c *gin.Context) {
}
func read(c *gin.Context) {
}
package main
import (
"github.com/gin-gonic/gin"
)
type LoginForm struct {
Username string `form:"username" binding:"required"`
Password string `form:"password" binding:"required"`
}
func main() {
router := gin.Default()
router.POST("/login", func(c *gin.Context) {
var form LoginForm
if c.ShouldBind(&form) == nil {
if form.Username == "user" && form.Password == "password" {
c.JSON(200, gin.H{"status": "you are logged in"})
} else {
c.JSON(401, gin.H{"status": "not authorized"})
}
}
})
router.Run(":8058")
}
2、gin-cookie:
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
router := gin.Default()
router.GET("/cookie", func(c *gin.Context) {
// 设置cookie
c.SetCookie("my_cookie", "cookievalue", 3600, "/", "localhost", false, true)
})
r.Run(":8068")
}
func Handler(c *gin.Context) {
// 根据cookie名字读取cookie值
data, err := c.Cookie("my_cookie")
if err != nil {
// 直接返回cookie值
c.String(200,data)
return
}
c.String(200,"not found!")
}
3、gin-file:
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
r.GET("/hi", func(c *gin.Context) {
//通过File函数,直接返回本地文件,参数为本地文件地址。
//函数说明:c.File("文件路径")
c.File("/var/www/gin/test.jpg")
})
r.Run(":8068")
}
4、gin-fileupload:
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"log"
"net/http"
)
func main() {
router := gin.Default()
// 设置文件上传大小限制,默认是32m
router.MaxMultipartMemory = 64 << 20 // 64 MiB
router.POST("/upload", func(c *gin.Context) {
// 获取上传文件,返回的是multipart.FileHeader对象,
// 代表一个文件,里面包含了文件名之类的详细信息
// file是表单字段名字
file, _ := c.FormFile("file")
// 打印上传的文件名
log.Println(file.Filename)
// 将上传的文件,保存到./data/shirdon.jpg 文件中
c.SaveUploadedFile(file, "./data/shirdon.jpg")
c.String(http.StatusOK, fmt.Sprintf("'%s' uploaded!", file.Filename))
})
router.Run(":8086")
}
upload.html:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Gin 上传文件示例</title>
</head>
<body>
<h1>上传文件示例</h1>
<form action="http://127.0.0.1:8086/upload" method="post" enctype="multipart/form-data">
文件: <input type="file" name="file"><br><br>
<input type="submit" value="上传">
</form>
</body>
</html>
5、gin-header:
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
r.GET("/hi", func(c *gin.Context) {
c.Header("Content-Type", "text/html; charset=utf-8")
c.Header("site","shirdon")
})
r.Run(":8068")
}
6、gin-hello:
package main
import (
"github.com/gin-gonic/gin"
)
func main() {
// 创建一个默认的路由引擎
r := gin.Default()
// GET:请求方式;/hello:请求的路径
// 当客户端以GET方法请求/hello路径时,会执行后面的匿名函数
r.GET("/hello", func(c *gin.Context) {
// c.JSON:返回JSON格式的数据
c.JSON(200, gin.H{
"message": "Hello world!",
})
})
// 启动HTTP服务,默认在0.0.0.0:8080启动服务
r.Run()
}
7、gin-middleware:
package main
// 导入gin包
import (
"github.com/gin-gonic/gin"
"log"
"time"
)
// 自定义个日志中间件
func Logger() gin.HandlerFunc {
return func(c *gin.Context) {
t := time.Now()
// 可以通过上下文对象,设置一些依附在上下文对象里面的键/值数据
c.Set("example", "hi!这是一个中间件数据")
// 在这里处理请求到达控制器函数之前的逻辑
// 调用下一个中间件,或者控制器处理函数,具体得看注册了多少个中间件。
c.Next()
// 在这里可以处理请求返回给用户之前的逻辑
latency := time.Since(t)
log.Print(latency)
// 例如,查询请求状态吗
status := c.Writer.Status()
log.Println(status)
}
}
func main() {
r := gin.New()
// 注册上面自定义的日志中间件
r.Use(Logger())
r.GET("/hi", func(c *gin.Context) {
// 查询我们之前在日志中间件,注入的键值数据
example := c.MustGet("example").(string)
// it would print: "hi!"
log.Println(example)
})
// Listen and serve on 0.0.0.0:8080
r.Run(":8080")
}
8、gin-redis:
package main
import (
"github.com/gin-contrib/sessions"
"github.com/gin-contrib/sessions/redis"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
// 初始化基于Redis的存储引擎
// 参数说明:
// 第1个参数 - Redis最大的空闲连接数
// 第2个参数 - 数通信协议tcp或者udp
// 第3个参数 - Redis地址, 格式,host:port
// 第4个参数 - Redis密码
// 第5个参数 - session加密密钥
store, _ := redis.NewStore(10, "tcp", "localhost:6379", "", []byte("passord"))
r.Use(sessions.Sessions("mysession", store))
r.GET("/incr", func(c *gin.Context) {
session := sessions.Default(c)
var count int
v := session.Get("count")
if v == nil {
count = 0
} else {
count = v.(int)
count++
}
session.Set("count", count)
session.Save()
c.JSON(200, gin.H{"count": count})
})
r.Run(":8000")
}
9、gin-router:
package main
import "github.com/gin-gonic/gin"
func main() {
router := gin.Default()
// 创建v1组
v1 := router.Group("/v1")
{
v1.POST("/login", login)
}
// 创建v2组
v2 := router.Group("/v2")
{
v2.POST("/login", login)
}
router.Run(":8080")
}
10、gin-session:
package main
import (
// 导入session包
"github.com/gin-contrib/sessions"
// 导入session存储引擎
"github.com/gin-contrib/sessions/cookie"
// 导入gin框架包
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
// 创建基于cookie的存储引擎,password123456参数是用于加密的密钥
store := cookie.NewStore([]byte("password123456"))
// 设置session中间件,参数mysession,指的是session的名字,也是cookie的名字
// store是前面创建的存储引擎,我们可以替换成其他存储引擎
r.Use(sessions.Sessions("mysession", store))
r.GET("/hello", func(c *gin.Context) {
// 初始化session对象
session := sessions.Default(c)
// 通过session.Get读取session值
// session是键值对格式数据,因此需要通过key查询数据
if session.Get("hello") != "world" {
// 设置session数据
session.Set("hello", "world")
// 删除session数据
session.Delete("shirdon")
// 保存session数据
session.Save()
// 删除整个session
// session.Clear()
}
c.JSON(200, gin.H{"hello": session.Get("hello")})
})
r.Run(":8000")
}
func Handler(c *gin.Context) {
// 根据cookie名字读取cookie值
data, err := c.Cookie("my_cookie")
if err != nil {
// 直接返回cookie值
c.String(200, data)
return
}
c.String(200, "not found!")
}
11、gin-static:
package main
import "github.com/gin-gonic/gin"
func main() {
router := gin.Default()
router.Static("/assets", "/var/www/gin/assets")
router.StaticFile("/favicon.ico", "./static/favicon.ico")
// 启动服务
router.Run(":8080")
}
2024-06-18 start
13、gorm&restful:
package main
import (
"crypto/md5"
"encoding/hex"
"github.com/gin-gonic/gin"
_ "github.com/go-sql-driver/mysql"
"github.com/jinzhu/gorm"
"net/http"
)
var (
db *gorm.DB
sqlConnection = "root:a123456@tcp(127.0.0.1:3306)/chapter8?" +
"charset=utf8&parseTime=true"
)
//初始化
func init() {
//打开数据库连接
var err error
db, err = gorm.Open("mysql", sqlConnection)
if err != nil {
panic("failed to connect database")
}
db.AutoMigrate(&User{})
}
func main() {
router := gin.Default()
v2 := router.Group("/api/v2/user")
{
v2.POST("/", createUser) //POST方法,创建新用户
v2.GET("/", fetchAllUser) //GET方法,获取所有用户
v2.GET("/:id", fetchUser) //GET方法,获取某一个用户,形如:/api/v2/user/1
v2.PUT("/:id", updateUser) //PUT方法,更新用户,形如:/api/v2/user/1
v2.DELETE("/:id", deleteUser) //DELETE方法,删除用户,形如:/api/v2/user/1
}
router.Run("127.0.0.1:8086")
}
type (
// 数据表结构体类
User struct {
ID uint `json:"id"`
Phone string `json:"phone"`
Name string `json:"name"`
Password string `json:"password"`
}
//响应返回的结构体
UserRes struct {
ID uint `json:"id"`
Phone string `json:"phone"`
Name string `json:"name"`
}
)
//md5加密
func md5Password(str string) string {
h := md5.New()
h.Write([]byte(str))
return hex.EncodeToString(h.Sum(nil))
}
// 创建新用户
func createUser(c *gin.Context) {
phone := c.PostForm("phone") //获取POST请求参数phone
name := c.PostForm("name") //获取POST请求参数name
user := User{
Phone: phone,
Name: name,
Password: md5Password("666666"), //用户密码
}
db.Save(&user) //保存到数据库
c.JSON(
http.StatusCreated,
gin.H{
"status": http.StatusCreated,
"message": "User created successfully!",
"ID": user.ID,
}) //返回状态到客户端
}
// 获取所有用户
func fetchAllUser(c *gin.Context) {
var user []User //定义一个数组去数据库总获取数据
var _userRes []UserRes //定义一个响应数组用户返回数据到客户端
db.Find(&user)
if len(user) <= 0 {
c.JSON(
http.StatusNotFound,
gin.H{
"status": http.StatusNotFound,
"message": "No user found!",
})
return
}
//循环遍历,追加到响应数组
for _, item := range user {
_userRes = append(_userRes,
UserRes{
ID: item.ID,
Phone: item.Phone,
Name: item.Name,
})
}
c.JSON(http.StatusOK,
gin.H{"status":
http.StatusOK,
"data": _userRes,
}) //返回状态到客户端
}
// 获取单个用户
func fetchUser(c *gin.Context) {
var user User //定义User结构体
ID := c.Param("id") //获取参数id
db.First(&user, ID)
if user.ID == 0 { //如果用户不存在,则返回
c.JSON(http.StatusNotFound,
gin.H{"status": http.StatusNotFound, "message": "No user found!"})
return
}
//返回响应结构体
res := UserRes{ID: user.ID, Phone: user.Phone, Name: user.Name}
c.JSON(http.StatusOK, gin.H{"status": http.StatusOK, "data": res})
}
//更新用户
func updateUser(c *gin.Context) {
var user User //定义User结构体
userID := c.Param("id") //获取参数id
db.First(&user, userID) //查找数据库
if user.ID == 0 { //如果数据库不存在,则返回
c.JSON(http.StatusNotFound,
gin.H{"status": http.StatusNotFound, "message": "No user found!"})
return
}
//更新对应的字段值
db.Model(&user).Update("phone", c.PostForm("phone"))
db.Model(&user).Update("name", c.PostForm("name"))
c.JSON(http.StatusOK,
gin.H{"status": http.StatusOK, "message": "Updated User successfully!"})
}
// 删除用户
func deleteUser(c *gin.Context) {
var user User //定义User结构体
userID := c.Param("id") //获取参数id
db.First(&user, userID) //查找数据库
if user.ID == 0 { //如果数据库不存在,则返回
c.JSON(http.StatusNotFound,
gin.H{"status": http.StatusNotFound, "message": "No user found!"})
return
}
//删除用户
db.Delete(&user)
c.JSON(http.StatusOK,
gin.H{"status": http.StatusOK, "message": "User deleted successfully!"})
}
实现 Tabler
接口:在结构体中定义一个名为 TableName
的无参数函数,返回表名字符串。
func (Video) TableName() string {
return "spider_video"
}
end
2024-06-19 start:
使用泛型和包装器进行数据对象的转换:
package main
import (
"time"
)
// 定义一个泛型转换函数
func Convert[T, U any](items []T, converter func(T) U) []U {
result := make([]U, len(items))
for i, item := range items {
result[i] = converter(item)
}
return result
}
type Video struct {
ID int `json:"id"`
VideoName string `json:"video_name"`
VideoIcon string `json:"video_icon"`
VideoSearchID int `json:"video_search_id"`
CreateTime *time.Time `json:"create_time"`
UpdateTime *time.Time `json:"update_time"`
DetailURL string `json:"-"`
}
func (Video) TableName() string {
return "spider_video"
}
// VideoRes 响应返回的结构体
type VideoRes struct {
ID int `json:"id"`
VideoName string `json:"video_name"`
VideoIcon string `json:"video_icon"`
}
// 定义一个转换单个Video到VideoRes的函数
func convertVideoToVideoRes(video Video) VideoRes {
return VideoRes{
ID: video.ID,
VideoName: video.VideoName,
VideoIcon: video.VideoIcon,
}
}
func main() {
// 示例:创建Video对象数组
videos := []Video{
{ID: 1, VideoName: "Video 1", VideoIcon: "/path/to/icon1.png"},
{ID: 2, VideoName: "Video 2", VideoIcon: "/path/to/icon2.png"},
}
// 使用泛型Convert函数转换Video数组到VideoRes数组
videoResList := Convert(videos, convertVideoToVideoRes)
// 打印转换后的结果,此处省略打印代码
// ...
}
end