【golang-web-gin】

Gin框架

1.Gin网络请求和路由处理

1.1 创建Engine

  • gin.Default()
    • 默认使用loggerrecovery中间件
      • logger 日志
      • recovery 如果错误会报错并且返回错误
  • gin.New()
// 创建engine的方式1 推荐使用
r1 := gin.Default()
// 创建engine的方式2
r2 := gin.New()

1.2 Engine对象的方法

  • context.FullPath():获取请求的路径
  • context.DefaultQuery(key, defaultValue string):获取GET请求的参数
    • key:query的key
    • defaultValue :如果获取不到默认值
  • context.PostForm(key string):获取POST请求的参数
    • key:form的key
  • context.Param(key string):获取DELETE请求的参数(/user/:id)
    • key:url中的参数key
  • context.Writer.Write([]byte("data")):返回给页面的内容

1.3 request请求处理方式

1.3.1 handle通用处理

  • handle处理

    func (group *RouterGroup) Handle(httpMethod, relativePath string, handlers ...HandlerFunc) IRoutes {
    
    • httpMethod:请求方式
    • relativePath:请求地址
    • HandlerFunc:处理函数
/*
	handle处理http请求
*/
package main

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

func main(){
	// 创建一个引擎对象
	engine := gin.Default()


	// 1.handle处理
	// handle处理get请求
	// http://127.0.0.1:8000/hello?name=huhao
	engine.Handle("GET","/hello", func(context *gin.Context) {
		// context.FullPath() 请求接口
		fmt.Println(context.FullPath())

		// context.DefaultQuery() 获取get请求参数
		name := context.DefaultQuery("name","default alex")
		fmt.Println(name)

		// context.Writer.Write() 返回给页面的内容
		context.Writer.Write([]byte("hello"+name))
	})

	// handle处理post请求
	// http://127.0.0.1:8000/hello?name=huhao
	engine.Handle("POST","/login", func(context *gin.Context) {
		// context.FullPath() 请求接口
		fmt.Println(context.FullPath())

		// context.DefaultQuery() 获取get请求参数
		username := context.PostForm("username")
		password := context.PostForm("password")
		fmt.Println(username)
		fmt.Println(password)

		// context.Writer.Write() 返回给页面的内容
		if username=="huhao"&&password=="123" {
			context.Writer.Write([]byte(username+"登录"))
		}else{
			context.Writer.Write([]byte(username+"用户名或者密码错误"))
		}

	})

	//运行
	engine.Run("127.0.0.1:8000")

}

1.3.2 分类处理请求

  • 分类处理

    • engine.GET
    func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes {
    
    • engine.POST
    func (group *RouterGroup) POST(relativePath string, handlers ...HandlerFunc) IRoutes {
    
    • engine.DELETE
    func (group *RouterGroup) DELETE(relativePath string, handlers ...HandlerFunc) IRoutes {
    
    • engine.PUT
    func (group *RouterGroup) PUT(relativePath string, handlers ...HandlerFunc) IRoutes {
    
    • relativePath:请求地址
    • HandlerFunc:处理函数
/*
	分类处理http请求
*/
package main

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

func main(){
	// 创建一个引擎对象
	engine := gin.Default()

	engine.GET("/hello", func(context *gin.Context) {
		// context.FullPath() 请求接口
		fmt.Println(context.FullPath())

		// context.DefaultQuery() 获取get请求参数
		name := context.DefaultQuery("name","default alex")
		fmt.Println(name)

		// context.Writer.Write() 返回给页面的内容
		context.Writer.Write([]byte("hello"+name))
	})

	engine.POST("/login", func(context *gin.Context) {
			// context.FullPath() 请求接口
			fmt.Println(context.FullPath())

			// context.DefaultQuery() 获取get请求参数
			username := context.PostForm("username")
			password := context.PostForm("password")
			fmt.Println(username)
			fmt.Println(password)

			// context.Writer.Write() 返回给页面的内容
			if username=="huhao"&&password=="123" {
				context.Writer.Write([]byte(username+"登录"))
			}else{
				context.Writer.Write([]byte(username+"用户名或者密码错误"))
			}
	})
	engine.DELETE("/user/:id", func(context *gin.Context) {
		// context.FullPath() 请求接口
		fmt.Println(context.FullPath())

		// context.DefaultQuery() 获取get请求参数
		id := context.Param("id")
		fmt.Println(id)

		// 返回
		context.Writer.Write([]byte("id为"+id+"的户名已删除"))

	})

	//运行
	engine.Run("127.0.0.1:8001")

}

1.4 表单实体绑定

image-20210507022252829

1.4.1 GET请求

  • context.ShouldBindQuery(&stu)

    package main
    
    import (
    	"fmt"
    	"github.com/gin-gonic/gin"
    	"log"
    )
    
    // 1.创建一个学生的结构体
    type Student struct {
    	Name string `form:"name"`
    	Classes string `form:"classes"`
    }
    
    func main(){
    	r := gin.Default()
    	//http://127.0.0.1:8000/hello?name=alex&classes=软件工程
    	r.GET("/hello", func(context *gin.Context) {
    		fmt.Println(context.FullPath())
    
    		// 2.创建一个结构体的实例 通过 context.ShouldBindQuery(&stu) 的方式去绑定
    		var stu Student
    		err := context.ShouldBindQuery(&stu)
    		if err!=nil{
    			log.Fatal(err.Error())
    			return
    		}
    		fmt.Println(stu.Name)
    		fmt.Println(stu.Classes)
    		context.Writer.Write([]byte("hello,"+stu.Name))
    	})
    	r.Run("127.0.0.1:8002")
    }
    

1.4.2 POST请求表单

  • context.ShouldBind(&register)

    package main
    
    import (
    	"fmt"
    	"github.com/gin-gonic/gin"
    	"log"
    )
    
    
    func main(){
    	// 1.创建一个学生的结构体
    	type Register struct {
    		UserName string `form:"name"`
    		Phone string `form:"phone"`
    		Password string `form:"password"`
    
    	}
    
    	r := gin.Default()
    	//http://127.0.0.1:8000/hello
    	r.POST("/hello", func(context *gin.Context) {
    		fmt.Println(context.FullPath())
    
    		// 2.创建一个结构体的实例 通过 context.ShouldBind(&stu) 的方式去绑定
    		var register Register
    		err := context.ShouldBind(&register)
    		if err!=nil{
    			log.Fatal(err.Error())
    			return
    		}
    		fmt.Println(register.UserName)
    		fmt.Println(register.Phone)
    		fmt.Println(register.Password)
    		context.Writer.Write([]byte("Register,"+register.UserName))
    	})
    	r.Run("127.0.0.1:8002")
    }
    

1.4.3 POST请求json

  • context.BindJSON(&person)

    package main
    
    import (
    	"fmt"
    	"github.com/gin-gonic/gin"
    	"log"
    )
    
    
    func main(){
    	// 1.创建一个学生的结构体
    	type Person struct {
    		//约束了数据类型
    		Name string `form:"name"`
    		Sex string `form:"sex"`
    		Age string `form:"age"`
    
    	}
    
    	r := gin.Default()
    	//http://127.0.0.1:8000/addstudent
    	r.POST("/addstudent", func(context *gin.Context) {
    		fmt.Println(context.FullPath())
    
    		// 2.创建一个结构体的实例 通过 context.ShouldBind(&stu) 的方式去绑定
    		var person Person
    		err := context.BindJSON(&person)
    		if err!=nil{
    			log.Fatal(err.Error())
    			return
    		}
    		fmt.Println(person.Name)
    		fmt.Println(person.Sex)
    		fmt.Println(person.Age)
    		context.Writer.Write([]byte("addstudent,"+person.Name))
    	})
    
    	r.Run("127.0.0.1:8003")
    }
    

1.5 response应答

1.5.1 切片数组

  • byte[]()

    func main() {
       r := gin.Default()
    
       // 返回byte数组
       r.GET("/byte", func(context *gin.Context) {
          path := context.FullPath()
          fmt.Println(path)
          context.Writer.Write([]byte(path))
       })
    
       r.Run("127.0.0.1:8004")
    }
    

1.5.2 字符串

  • string

    func main() {
       r := gin.Default()
    
       // 返回string
       r.GET("/string", func(context *gin.Context) {
          path := context.FullPath()
          fmt.Println(path)
          context.Writer.WriteString(path)
       })
       
       r.Run("127.0.0.1:8004")
    }
    

1.5.3 json

  • json-map

    func main() {
       r := gin.Default()
       
       // 返回Json
       r.GET("/json", func(context *gin.Context) {
          path := context.FullPath()
          fmt.Println(path)
          context.JSON(200, map[string]interface{}{
             "code":200,
             "msg":"ok",
             "data":"json",
          })
       })
    
       r.Run("127.0.0.1:8004")
    }
    
  • json-struct

    package main
    
    import (
    	"fmt"
    	"github.com/gin-gonic/gin"
    )
    //1.定义一个response结构体
    type Response struct {
    	Code int
    	Msg string
    	Data interface{}
    }
    func main() {
    	r := gin.Default()
    	// 返回Json--结构体
    	r.GET("/json_struct", func(context *gin.Context) {
    		path := context.FullPath()
    		fmt.Println(path)
    		//map类型转换为json
    		//2.实例化一个结构体
    		resp := Response{
    			Code: 200,
    			Msg: "OK",
    			Data:path,
    		}
    		context.JSON(200,&resp)
    	})
    	r.Run("127.0.0.1:8005")
    }
    
    

    1.5.3 HTML

    package main
    
    import (
    	"fmt"
    	"github.com/gin-gonic/gin"
    	"net/http"
    )
    func main() {
    	r := gin.Default()
    	//1.指名加载html的目录
    	//r.LoadHTMLGlob("/gin_webframework/03Response/html/*")
    	r.LoadHTMLGlob(".\\html\\*")
    
    	r.GET("/html", func(context *gin.Context) {
    		path := context.FullPath()
    		fmt.Println(path)
    
    		//2.加载html页面
    		//第一个参数:请求的状态码
    		//第二个参数:模板路径
    		//第三个参数:传递的参数
    		context.HTML(http.StatusOK,"index.html",gin.H{
    			"fullpath":path,
    		})
    	})
    
    
    	r.Run("127.0.0.1:8007")
    }
    

2.使用路由组分类处理请求

2.1 Group

  • 在项目开发中,模块化开发会使用相同的prefix接口前缀要用到group

2.2 封装

  • main函数中只写接口
package main

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

func main() {
	r := gin.Default()
	//第一个参数:分组的path
	user := r.Group("/user")
	user.POST("/register", registerHandle)
	user.GET("/login", loginHandle)
	user.DELETE("/:id", deleteHandle)
	r.Run(":8010")
}
func registerHandle(context *gin.Context) {
	path := "用户注册" + context.FullPath()
	fmt.Println(path)
	context.Writer.WriteString(path)
}
func loginHandle(context *gin.Context) {
	path := "用户登录" + context.FullPath()
	fmt.Println(path)
	context.Writer.WriteString(path)
}
func deleteHandle(context *gin.Context) {
	path := "删除登录" + context.FullPath()
	UserID := context.Param("id")
	fmt.Println(path)
	context.Writer.WriteString(path + UserID)
}

3.middleware中间件

  • 中间件可以处理一些公共的功能
    • 权限验证
    • 登录认证
    • 数据分页
    • 耗时统计
  • 可以进行beforerequestafterrequest
  • 类似于django-process_request
  • beforerequest中间件
    • token验证
    • 权限
    • 节流
    • 数据过滤
    • 白名单
  • afterrequest
    • 数据过滤
    • 统一相应头

image-20210507114944427

在web应用中一些统一处理的可以用中间件来实现。比如权限管理、登录状态验证、日志的等

3.1 自定义中间件

  • 自定义中间件
    • func函数
    • 返回值HandleFunc
//1.自定义请求方式的中间件
func RequestInfos() gin.HandlerFunc{
	return func(context *gin.Context) {
		path := context.FullPath()
		method := context.Request.Method
		fmt.Println("请求路径:"+path)
		fmt.Println("请求方式:"+method)
	}
}

3.2 使用中间件

  • 通过engine.use()全局使用中间件r.Use(RequestInfos())
func main() {
	r := gin.Default()
	//2.使用中间件
	r.Use(RequestInfos())

	r.GET("/login", loginHandle)

	r.Run(":8011")
}
func loginHandle(context *gin.Context) {
	context.Writer.WriteString("login")
}
  • 在具体请求中添加中间件可以局部使用r.GET("/login",RequestInfos(),loginHandle)
func main() {
	r := gin.Default()
	//2.使用中间件
	//	全局使用
	//r.Use(RequestInfos())
	//	局部使用
	r.GET("/login",RequestInfos(),loginHandle)
	r.Run(":8011")
}
func loginHandle(context *gin.Context) {
	context.Writer.WriteString("login")
}

3.3 context.Next()

  • 相当于beforerequest和afterrequest
//1.自定义请求方式的中间件
func RequestInfos() gin.HandlerFunc{

	return func(context *gin.Context) {
		path := context.FullPath()
		method := context.Request.Method
		code := context.Writer.Status()
		fmt.Println("请求路径:"+path)
		fmt.Println("请求方式:"+method)

		context.Next()//程序会往下走 不走下面的

		fmt.Println("状态码:",code)
	}
}
>>>
请求路径:/login
请求方式:GET
middleware使用
状态码: 200
[GIN] 2021/05/07 - 12:22:13 | 200 |            0s |       127.0.0.1 | GET      "/login"

3.4 代码示例

package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
)
/*
自定义中间件
	1.func函数
	2.返回值HandleFunc
*/

//1.自定义请求方式的中间件
func RequestInfos() gin.HandlerFunc{

	return func(context *gin.Context) {
		path := context.FullPath()
		method := context.Request.Method
		code := context.Writer.Status()
		fmt.Println("请求路径:"+path)
		fmt.Println("请求方式:"+method)

		context.Next()//程序会往下走 不走下面的

		fmt.Println("状态码:",code)
	}
}
func main() {

	r := gin.Default()
	//2.使用中间件
	//	全局使用
	//r.Use(RequestInfos())
	//	局部使用
	r.GET("/login",RequestInfos(),loginHandle)

	r.Run(":8011")
}

func loginHandle(context *gin.Context) {
	fmt.Println("middleware使用")
	context.Writer.WriteString("login")
}

3.4 Gin内置中间件

  • BasicAuth 权限管理
  • BasicAuthForRealm 认证分组
  • Bind 拦截参数绑定
  • ......

image-20210509053230131

4.Golang连接mysql

  • 创建驱动
  • 执行sql
package main

import (
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"log"
)

func main() {
	// 1.设置驱动
	//	"root:密码@tcp(ip:port)/数据库名称"
	connStr := "root:root@tcp(127.0.0.1:3306)/db01"
	db, err := sql.Open("mysql", connStr)
	if err != nil {
		log.Fatal(err.Error())
		return
	}
	
    //// 2.创建数据表
	//_, err = db.Exec("create table person(id int auto_increment primary key,name varchar(12) not null,age int default 1);")
	//if err != nil {
	//	log.Fatal(err.Error())
	//	return
	//} else {
	//	fmt.Println("数据表创建成功")
	//}
	
    // 3.插入数据
	_, err = db.Exec("insert into person(name,age) values(?,?)", "tom", 15)
	if err != nil {
		log.Fatal(err.Error())
		return
	} else {
		fmt.Println("插入数据成功")
	}

	// 4.查询数据
	rows, err := db.Query("select * from person;")
	if err != nil {
		log.Fatal(err.Error())
		return
	} else {
		fmt.Println("查询数据")
	}
	//rows.Next()==true表示有数据
	//数据的遍历输出
scan:
	if rows.Next(){
		person := new(Person)
		//从这一行中读
		err := rows.Scan(&person.Id,&person.Name,&person.Age)
		if err!=nil{
			log.Fatal(err.Error())
			return
		}
		fmt.Println(person.Id,person.Name,person.Age)
	}
	goto scan
}

type Person struct {
	Id int
	Name string
	Age int
}

5.数据绑定

5.1 ShouldBind

  • Form
  • QueryString
  • Json
package main

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

func main() {
	router := gin.Default()
	router.GET("/query_bind", QueryBind) //postman:param:
	router.POST("/form_bind", FormBind)  //postman:body:x-www-form-urlencoded
	router.POST("/json_bind", JsonBind)  //postman:body:row:json
	router.Run()
}

//绑定form和query和json可以使用form
type UserForm struct {
	Name string `form:"name"`
	Age  int    `form:"age"`
	Addr string `form:"addr"`
}

//绑定json可以使用json
type UserJson struct {
	Name string `json:"name"`
	Age  int    `json:"age"`
	Addr string `json:"addr"`
}

func FormBind(ctx *gin.Context) {
	var user UserForm
	err := ctx.ShouldBind(&user)
	fmt.Println(err, user.Age, user.Name, user.Addr)
	if err != nil {
		ctx.String(http.StatusNotFound, "Form绑定失败")
		return
	}
	ctx.String(http.StatusOK, "Form绑定成功")
	return
}
func QueryBind(ctx *gin.Context) {
	var user UserForm
	err := ctx.ShouldBind(&user)
	fmt.Println(err, user.Age, user.Name, user.Addr)
	if err != nil {
		ctx.String(http.StatusNotFound, "Query绑定失败")
		return
	}
	ctx.String(http.StatusOK, "Query绑定成功")
	return
}

//使用UserForm或者UserJson这个结构体
func JsonBind(ctx *gin.Context) {
	var user UserForm
	err := ctx.ShouldBind(&user)
	fmt.Println(err, user.Age, user.Name, user.Addr)
	if err != nil {
		ctx.String(http.StatusNotFound, "json绑定失败")
		return
	}
	ctx.String(http.StatusOK, "json绑定成功")
	return
}

5.2 ShouldBindUri

  • Uri
package main

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

func main() {
	router := gin.Default()
	router.GET("/uri_bind/:name/:age/:addr", UriBind) //url: /query_bind/:name/:age/:addr
	router.Run()
}

//绑定uri可以使用uri
type UserUri struct {
	Name string `uri:"name"`
	Age  int    `uri:"age"`
	Addr string `uri:"addr"`
}

//使用UserUri这个结构体
func UriBind(ctx *gin.Context) {
	var user UserUri
	err := ctx.ShouldBindUri(&user)
	fmt.Println(err, user.Age, user.Name, user.Addr)
	if err != nil {
		ctx.String(http.StatusNotFound, "uri绑定失败")
		return
	}
	ctx.String(http.StatusOK, "uri绑定成功")
	return
}

6.数据验证

  • binding
package main

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

func main() {
	router := gin.Default()
	router.POST("/valid", PostValidData)
	router.Run()
}

//绑定form和query和json可以使用form
/*
binding:"required" 不能为空
*/
type Article struct {
	Id      int    `form:"-"`//表示不做验证
	Title   string `form:"title" binding:"required"`//不能为空
	Content string `form:"content" binding:"required"`
	Desc    string `form:"desc" binding:"required"`
}

func PostValidData(ctx *gin.Context) {
	var article Article
	ctx.ShouldBind(&article)
	fmt.Println(article)
	ctx.String(http.StatusOK,"数据验证成功")
	return
}

7.路由分发

7.1 简单使用

  • 通过router.Group设置路由组
package main

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

func main() {
	router := gin.Default()
	v1 := router.Group("/api/v1")
	{
		User := v1.Group("/user")
		{
			User.GET("", UserGet)
			User.POST("", UserPost)
			User.PUT("", UserPut)
			User.DELETE("", UserDelete)
		}
	}
}
func UserGet(ctx *gin.Context) {
	path := ctx.FullPath()
	ctx.String(http.StatusOK, path+":UserGet")
}
func UserPost(ctx *gin.Context) {
	path := ctx.FullPath()
	ctx.String(http.StatusOK, path+":UserPost")
}
func UserPut(ctx *gin.Context) {
	path := ctx.FullPath()
	ctx.String(http.StatusOK, path+":UserPut")
}
func UserDelete(ctx *gin.Context) {
	path := ctx.FullPath()
	ctx.String(http.StatusOK, path+":UserDelete")
}

7.2 路由分组

# 目录结构
--root		# 根目录
	--controller
        --user				# user模块
            --api.go
            --router.go
        --order				# order模块
            --api.go
            --router.go
        --admin				# admin模块
            --api.go
            --router.go
        --router			# 总路由
            --router.go
    --static
    --template
    --utils
    --middleware
	--main.go				# 项目入口
//main.go
package main

import (
	router2 "gin_webframework/09urlgroup/router"
	"github.com/gin-gonic/gin"
)

func main() {
	router := gin.Default()
	router2.Router(router)
	router.Run()

}
//router/router.go
package router

import (
	Admin "gin_webframework/09urlgroup/admin"
	Order "gin_webframework/09urlgroup/order"
	User "gin_webframework/09urlgroup/user"
	"github.com/gin-gonic/gin"
)

func Router(router *gin.Engine) {
	v1 := router.Group("/api/v1")
	v2 := router.Group("/api/v2")

	{
		user := v1.Group("/user")
		admin := v1.Group("/admin")
		order := v1.Group("/order")
		Admin.Router(admin)
		User.Router(user)
		Order.Router(order)
	}
	{
		user := v2.Group("/user")
		admin := v2.Group("/admin")
		order := v2.Group("/order")
		Admin.Router(admin)
		User.Router(user)
		Order.Router(order)
	}
}
// admin/router.go
package admin

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

func Router(router *gin.RouterGroup){
	router.GET("", UserGet)
	router.POST("", UserPost)
	router.PUT("", UserPut)
	router.DELETE("", UserDelete)
}
// admin/api.go
package admin
import (
	"github.com/gin-gonic/gin"
	"net/http"
)

func UserGet(ctx *gin.Context) {
	path := ctx.FullPath()
	ctx.String(http.StatusOK, path+":UserGet")
}
func UserPost(ctx *gin.Context) {
	path := ctx.FullPath()
	ctx.String(http.StatusOK, path+":UserPost")
}
func UserPut(ctx *gin.Context) {
	path := ctx.FullPath()
	ctx.String(http.StatusOK, path+":UserPut")
}
func UserDelete(ctx *gin.Context) {
	path := ctx.FullPath()
	ctx.String(http.StatusOK, path+":UserDelete")
}
# console:
[GIN-debug] GET    /api/v1/admin             --> gin_webframework/09urlgroup/admin.UserGet (3 handlers)
[GIN-debug] POST   /api/v1/admin             --> gin_webframework/09urlgroup/admin.UserPost (3 handlers)
[GIN-debug] PUT    /api/v1/admin             --> gin_webframework/09urlgroup/admin.UserPut (3 handlers)
[GIN-debug] DELETE /api/v1/admin             --> gin_webframework/09urlgroup/admin.UserDelete (3 handlers)
[GIN-debug] GET    /api/v1/user              --> gin_webframework/09urlgroup/user.UserGet (3 handlers)
[GIN-debug] POST   /api/v1/user              --> gin_webframework/09urlgroup/user.UserPost (3 handlers)
[GIN-debug] PUT    /api/v1/user              --> gin_webframework/09urlgroup/user.UserPut (3 handlers)
[GIN-debug] DELETE /api/v1/user              --> gin_webframework/09urlgroup/user.UserDelete (3 handlers)
[GIN-debug] GET    /api/v1/order             --> gin_webframework/09urlgroup/order.UserGet (3 handlers)
[GIN-debug] POST   /api/v1/order             --> gin_webframework/09urlgroup/order.UserPost (3 handlers)
[GIN-debug] PUT    /api/v1/order             --> gin_webframework/09urlgroup/order.UserPut (3 handlers)
[GIN-debug] DELETE /api/v1/order             --> gin_webframework/09urlgroup/order.UserDelete (3 handlers)
[GIN-debug] GET    /api/v2/admin             --> gin_webframework/09urlgroup/admin.UserGet (3 handlers)
[GIN-debug] POST   /api/v2/admin             --> gin_webframework/09urlgroup/admin.UserPost (3 handlers)
[GIN-debug] PUT    /api/v2/admin             --> gin_webframework/09urlgroup/admin.UserPut (3 handlers)
[GIN-debug] DELETE /api/v2/admin             --> gin_webframework/09urlgroup/admin.UserDelete (3 handlers)
[GIN-debug] GET    /api/v2/user              --> gin_webframework/09urlgroup/user.UserGet (3 handlers)
[GIN-debug] POST   /api/v2/user              --> gin_webframework/09urlgroup/user.UserPost (3 handlers)
[GIN-debug] PUT    /api/v2/user              --> gin_webframework/09urlgroup/user.UserPut (3 handlers)
[GIN-debug] DELETE /api/v2/user              --> gin_webframework/09urlgroup/user.UserDelete (3 handlers)
[GIN-debug] GET    /api/v2/order             --> gin_webframework/09urlgroup/order.UserGet (3 handlers)
[GIN-debug] POST   /api/v2/order             --> gin_webframework/09urlgroup/order.UserPost (3 handlers)
[GIN-debug] PUT    /api/v2/order             --> gin_webframework/09urlgroup/order.UserPut (3 handlers)
[GIN-debug] DELETE /api/v2/order             --> gin_webframework/09urlgroup/order.UserDelete (3 handlers)
[GIN-debug] Environment variable PORT is undefined. Using port :8080 by default
[GIN-debug] Listening and serving HTTP on :8080

8.Gorm

8.1 增删改查

image-20210509143539902

  • 连接
    • 用户名:密码@tcp(ip:port)/数据库名称?charset=utf8&parseTime=True&loc=Local
package main

import (
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
)

//2.创建一个模型
//字段名称首字母大写
type User struct {
	gorm.Model //自动加上id ctime utime dtime
	Id int
	Name string
	Age int
	Addr string

}
//使用TableName重写表名称
func (User)TableName()string{
	return "test_gorm_table_name"
}

func main() {
	//1.创建数据库连接
	//连接数据库 用户名:密码@tcp(ip:port)/数据库名称?charset=utf8&parseTime=True&loc=Local
	db, err := gorm.Open("mysql", "root:root@tcp(127.0.0.1:3306)/db01?charset=utf8&parseTime=True&loc=Local")
	if err != nil {
		panic(err)
	}

	//3.创建表 不指定表明模型后面会+s
	db.CreateTable(&User{})	//users
	//4.指定表名创建表
	db.Table("user").CreateTable(&User{}) //user

	//5.删除表
	db.DropTable("user")	//删掉表名称为users的表 删除了user
	db.DropTable(&User{})	//按结构体老删除表 删除了users

	//6.检查表是否存在
	HasUser:=db.HasTable("user")
	fmt.Println(HasUser)	//true false
	HasUsers:=db.HasTable(&User{})
	fmt.Println(HasUsers)	//true false


	//统一给所有表加前缀后缀
	gorm.DefaultTableNameHandler = func(db *gorm.DB, defaultTableName string) string {
		return "sys_"+defaultTableName+"_sys"
	}

	//7.自动迁移数据表
	//自动迁移表仅仅是创建表,添加且少列和索引,并且不会改变现有列的类型,保护现有的数据
	db.AutoMigrate(&User{})	//可以传多个模型

	//8.增加
	db.Create(&User{Name: "张三",Age:18,Addr: "北京市朝阳区"})
	db.Create(&User{Name: "李四",Age:18,Addr: "北京市海淀区"})
	db.Create(&User{Name: "王五",Age:18,Addr: "北京市顺义区"})

	//9.查询
	//9.1查询第一条
	var user User
	//db.First(&user,1)	//默认根据id
	db.First(&user,"name=?","李四")//指定根据name去查询
	fmt.Println(user)

	////10.修改
	//var user User
	//db.First(&user,1)
	//db.Model(&user).Update("age",100)
	//fmt.Println(user)
	//
	////11.删除
	//var user User
	//db.First(&user,2)	//删除第二条数据
	//db.Delete(&user)

	defer db.Close()	//关闭空闲的连接

}

8.2 对应关系

  • 一对一
    • 在任意表中加外键
//属于:关系和外键在一起
type UserInfo struct {
	Id   int
	Name string
	Age  int
	Addr string
}
type UserProfile struct {
	Id       int
	Pic      string
	CPic     string
	Phone    string
	UserInfo UserInfo `gorm:"ForeignKey:UId;AssociationForeignKey:Id"` //关联关系
	UId      int      //默认关联字段UserID
}

//包含:关系和外键不在同一方
type UserInfo struct {
	Id   int
	Name string
	Age  int
	Addr string
    PId      int      //关联
}
type UserProfile struct {
	Id       int
	Pic      string
	CPic     string
	Phone    string
	UserInfo UserInfo `gorm:"ForeignKey:PId;AssociationForeignKey:Id"` //关联关系

}
  • 一对多

    • 在多的里面加外键
  • 多对多

    • 建立一张关系表
    id	a_id	b_id
    1	1		1
    2	1		2
    3	2		1
    

9.日志

package main

import (
   "fmt"
   "github.com/gin-gonic/gin"
   "io"
   "log"
   "net/http"
   "os"
)

func main(){
   router := gin.Default()

   //创建日志文件
   file,_ := os.Create("gin.log")
   gin.DefaultWriter = io.MultiWriter(file)

   router.GET("/hello", func(ctx *gin.Context) {
   	path := ctx.FullPath()
   	log.Fatal(path)
   	fmt.Println(path)
   	ctx.String(http.StatusOK,path)
   	return
   })
   router.Run()
}
posted @ 2021-05-09 18:49  GokuBlog  阅读(112)  评论(0)    收藏  举报