其他分享
首页 > 其他分享> > Day16 gin

Day16 gin

作者:互联网

 

01 web应用程序介绍 

数据库:存储数据的单元

前端:展示数据的单元

 

web层: 创建绑定 响应 这些功能都一样,重复。

业务层不一样,剔除业务层,其他的做成框架

只需填充业务代码即可

意义

  用于搭建Web应用程序

  免去不同Web应用相同代码部分的重复编写,只需关心Web应用核心的业务逻辑实现

web编程 特指浏览器发送的应用请求,按http协议响应

 

web框架和web应用程序关系:

  Web 框架包含一系列库和一个主要的处理器 (handler),通过构建代码实现 Web 应用

02 web开发流程

===

http

请求协议:

请求首行: get 请求方式 /s?key=value请求路径 HTTP/1.1请求协议

请求头: user-agent:”win chrome”

空行

请求体 (post请求数据)

===

响应协议

响应首行 HTTP/1.1 200 ok

响应头: server-name:gin 响应服务器、响应时间、等

空行

响应体:”动态页面”

前后端不分离

数据直接嵌入到页面返回给客户端

 

03 gin下载与简单案例

1 安装

下载

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

导入

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

(可选)

import "net/http"

====

使用go mod方式。

1 编写 go后缀文件

引入 import githob.com/gin-gonic/gin

2 初始化

go mod init demo

3 自动整理下载

go mod tidy

小案例

package main

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

func test(c *gin.Context){
   fmt.Println("test...")
   c.String(200,"hello world")
}

func main() {
   r:=gin.Default()
   //返回一个json数据
   r.GET("/test",test)
   r.Run()
}  

04 restful

REST的含义就是客户端与Web服务器之间进行交互的时候,使用HTTP协议中的请求方法代表不同的动作

 

restful接口规范

rpc接口

软件架构模式

没有遵循restful风格,通过url路径区分请求

/add_book/ add_book()

/select_book/ select_book()

/update_book/ update_book()

/delete_book/ delete_book()

 

通过GET POST 请求方法 符合restful规范接口

GET /books/ select_book()

POST /books/ add_book()

PUT /books/1 update_book()

DELETE /books/1 delete_book()

示例

package main

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

func test(c *gin.Context){
   fmt.Println("test...")
   c.String(http.StatusOK,"hello world")
}
func selectBook(c *gin.Context){
   c.String(http.StatusOK,"查询书籍")
}
func addBook(c *gin.Context){
   c.String(http.StatusOK,"添加书籍")
}
func updateBook(c *gin.Context){
   c.String(http.StatusOK,"更新书籍")
}
func deleteBook(c *gin.Context){
   c.String(http.StatusOK,"删除书籍")
}

func main() {
   r:=gin.Default()
 
   r.GET("/test",test)
   r.GET("/books",selectBook)
   r.POST("/books",addBook)
   r.PUT("/books",updateBook)
   r.DELETE("/books/1",deleteBook)
   r.Run()
}

postman

 

05 路由方法

OPTIONS 请求跨域的方法

Any 任意路由

package main

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

func test(c *gin.Context) {
   c.String(http.StatusOK, "测试页!")
}

func main() {
   r := gin.Default()
   r.Any("/test", test)
   r.Run()
}

测试

 

 

 

noRoute

package main

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

func test(c *gin.Context) {
   c.String(http.StatusOK, "测试页!")
}

func noMatch(c *gin.Context){
   c.String(200,"没有匹配的路由,请重新发起请求!")
}

func main() {
   r := gin.Default()
   r.Any("/test", test)
   r.NoRoute(noMatch)

   r.Run()

}

路由分组

package main

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

func test(c *gin.Context) {
   c.String(http.StatusOK, "测试页!")
}
func shop(c *gin.Context) {
   c.String(200, "购物商城")
}
func cart(c *gin.Context) {
   c.String(200, "购物车")
}

func noMatch(c *gin.Context) {
   c.String(200, "没有匹配的路由,请重新发起请求!")
}

func main() {
   r := gin.Default()
   r.Any("/test", test)
   r.GET("/app01/shop", shop)
   r.GET("/app01/cart", cart)
   r.NoRoute(noMatch)
   r.Run()
}

维护性太差

func shop(c *gin.Context){
   c.String(http.StatusOK,"购物商城")
}
func cart(c *gin.Context){
   c.String(http.StatusOK,"购物车")
}

 

r.GET("/app01/shop",shop)
r.GET("/app01/cart",cart) 

改为分组

func main() {
   r := gin.Default()
   r.Any("/test", test)
   //r.GET("/app01/shop", shop)
   //r.GET("/app01/cart", cart)

   //路由分组
   app01Group:=r.Group("/app01")
   app01Group.GET("/shop",shop)
   app01Group.GET("/cart",cart)
   r.NoRoute(noMatch)
   r.Run()
} 

嵌套分组

func main() {
   r := gin.Default()
   r.Any("/test", test)
   //r.GET("/app01/shop", shop)
   //r.GET("/app01/cart", cart)
   //路由分组
   //app01Group:=r.Group("/app01")
   //app01Group.GET("/shop",shop)
   //app01Group.GET("/cart",cart)
   //嵌套分组
   app01Group:=r.Group("/app01")
   app01Shop:=app01Group.Group("/shop")
   app01Shop.GET("/index",shop)
   app01Shop.GET("/cart",cart)

   r.NoRoute(noMatch)
   r.Run()
}

 

 

第二节 06 Gin视图 获取请求数据

请求参数和响应信息获取

获取基本请求信息

信息:

  请求方式

  请求ip

获取请求方式和请求路径URL

func test(c *gin.Context){
   fmt.Println("请求方式:",c.Request.Method)  //GET
   fmt.Println("请求路径:",c.Request.URL)    // /test
   c.String(http.StatusOK,"test...")
}

 

func main() {
   r:=gin.Default()
   r.Any("/test",test)
   _ =r.Run()
}  

请求头c.Request.Header

func test(c *gin.Context){
   fmt.Println("请求方式:",c.Request.Method)  //GET
   fmt.Println("请求路径:",c.Request.URL)    // /test
   fmt.Println("请求头:",c.Request.Header)      //
   c.String(http.StatusOK,"test...")
}

请求方式: GET
请求路径: /test
请求头: map[Accept:[text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9] Accept-Encoding:[gzip, deflate, br] Accept-Language:[zh-CN,zh;q=0.9] Cache-Control:[max-age=0] Connection:[keep-alive] Sec-Ch-Ua:[" Not A;Brand";v="99", "Chromium";v="100", "Google Chrome";v="100"] Sec-Ch-Ua-Mobile:[?0] Sec-Ch-Ua-Platform:["Windows"] Sec-Fetch-Dest:[document] Sec-Fetch-Mode:[navigate] Sec-Fetch-Site:[none] Sec-Fetch-User:[?1] Upgrade-Insecure-Requests:[1] User-Agent:[Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36]]

获取请求头

func test(c *gin.Context){
   fmt.Println("请求方式:",c.Request.Method)  //GET
   fmt.Println("请求路径:",c.Request.URL)    // /test
   fmt.Println("请求头:",c.Request.Header)      //
   fmt.Println("请求头:",c.Request.Header["User-Agent"])    //
   fmt.Println("请求头:",c.GetHeader("User-Agent"))     //
   c.String(http.StatusOK,"test...")
}

请求方式: GET
请求路径: /test
请求头: map[Accept:[text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9] Accept-Encoding:[gzip, deflate, br] Accept-Language:[zh-CN,zh;q=0.9] Cache-Control:[max-age=0] Connection:[keep-alive] Sec-Ch-Ua:[" Not A;Brand";v="99", "Chromium";v="100", "Google Chrome";v="100"] Sec-Ch-Ua-Mobile:[?0] Sec-Ch-Ua-Platform:["Windows"] Sec-Fetch-Dest:[document] Sec-Fetch-Mode:[navigate] Sec-Fetch-Site:[none] Sec-Fetch-User:[?1] Upgrade-Insecure-Requests:[1] User-Agent:[Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36]]
请求头: [Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36]
请求头: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36

获取请求ip

func test(c *gin.Context){
   c.String(http.StatusOK,"test...")
   fmt.Println("请求IP:",c.Request.RemoteAddr)
   fmt.Println("请求IP:",c.ClientIP())
}

请求IP: 127.0.0.1:52647
请求IP: 127.0.0.1

06-02 请求数据的获取

获取GET请求参数

Query

DefaultQuery

没查到返回默认值

GetQuery

返回 bool值

func test(c *gin.Context){
   c.String(http.StatusOK,"test...")
   //GET请求数据的获取
   fmt.Println(c.Query("name"))
   fmt.Println(c.DefaultQuery("name","root"))
   fmt.Println(c.GetQuery("name"))
}

访问:http://127.0.0.1:8080/test?name=zhangsan
发送name数据,返回:
zhangsan
zhangsan
zhangsan true
访问:http://127.0.0.1:8080/test?user=zhangsan
没发送name数据,返回:返回空 DefaultQuery返回默认值 GetQuery返回false 

root
 false

示例:应用返回的bool值

func test(c *gin.Context){
   c.String(http.StatusOK,"test...")
   //GET请求数据的获取
   fmt.Println(c.Query("name"))
   fmt.Println(c.DefaultQuery("name","root"))
   fmt.Println(c.GetQuery("name"))
   value,isExist:=c.GetQuery("name")
   if isExist{
      fmt.Println("value",value)
   }else{
      fmt.Println("没有传入name数据")
   }
}
func main() {
   r:=gin.Default()
   r.Any("/test",test)
   _ =r.Run()
}


请求:http://127.0.0.1:8080/test?user=zhangsan
返回

root
 false
没有传入name数据

请求:http://127.0.0.1:8080/test?name=zhangsan
返回
zhangsan
zhangsan
zhangsan true
value zhangsan

获取Post请求参数

PostForm

DefaultPostForm

GetPostForm

package main

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

func test(c *gin.Context){

   //(3) POST请求数据的获取 PostForm:解析contentType="urlencoded"
   fmt.Println(c.PostForm("user"))
   fmt.Println(c.DefaultPostForm("user","admin"))
   fmt.Println(c.GetPostForm("user"))
   c.String(200,"test...")
}

func main() {
   r:=gin.Default()
   r.Any("/test",test)
   _=r.Run()
}

返回结果:
user01
user01
user01 true

 

 

返回结果

admin
 false

数据类型标识,格式

浏览器请求协议:

浏览器请求协议:
""
post /s HTTP/1.1
user-agent:"win-chrome"
contentType:"json"
...
user=yuan&pwd=123
{"user":"user1","pwd":"123"}
请求体(post请求)
""

07 登录页面

demo\templates\index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h3>这是一个首页页面</h3>
</body>
</html>

demo\main.go

package main

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

func test(c *gin.Context){
   c.HTML(200,"index.html",nil)
}

func main() {
   r:=gin.Default()
   r.LoadHTMLGlob("templates/*")
   r.Any("/test",test)

   _=r.Run()
}

下午1 登录页面

demo\templates\login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/login" method="post">
    用户名:<input type="text" name="user">
    密码:<input type="password" name="pwd">
    <input type="submit">
</form>
</body>
</html>

 

demo\main.go

package main

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

func test(c *gin.Context){
   c.HTML(200,"index.html",nil)
}

func loginHtml(c *gin.Context){
   c.HTML(200,"login.html",nil)
}
func loginAuth(c *gin.Context){
   //获取用户名和密码
   user:=c.PostForm("user")
   pwd:=c.PostForm("pwd")
   if user=="root" && pwd=="123" {
      //响应成功
      c.String(200,"登录成功!")
   }else{
      //响应失败
      c.String(200,"用户名或者密码错误!")
   }
}


func main() {
   r:=gin.Default()
   r.LoadHTMLGlob("templates/*")
   r.Any("/test",test)
   r.GET("/login",loginHtml)
   r.POST("/login",loginAuth)
   _=r.Run()
}

 

下午2路径参数

r.GET("/article/:year/:month",article)
对应

y:=c.Param("year")

m:=c.Param("month")

 

package main

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

func test(c *gin.Context){
   c.String(200,"test...")
}

func loginHtml(c *gin.Context)  {
   c.HTML(200,"login.html",nil)
}

func loginAuth(c *gin.Context){
   user:=c.PostForm("user")
   pwd:=c.PostForm("pwd")
   if user=="root" && pwd=="123"{
      c.String(200,"登录成功!")
   }else{
      c.String(200,"用户名或者密码错误!")
   }
}

func article(c *gin.Context)  {
   y:=c.Param("year")
   fmt.Println(y)
   c.String(200,y)
}

func main() {
   r:=gin.Default()
   r.LoadHTMLGlob("templates/*")
   r.Any("/test",test)
   r.GET("/login",loginHtml)
   r.POST("/login",loginAuth)
   r.GET("/article/:year",article)
   _=r.Run()
}

 

 

 

 

添加带月份的路径参数

 

package main

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

func test(c *gin.Context){
   c.String(200,"test...")
}

func loginHtml(c *gin.Context)  {
   c.HTML(200,"login.html",nil)
}

func loginAuth(c *gin.Context){
   user:=c.PostForm("user")
   pwd:=c.PostForm("pwd")
   if user=="root" && pwd=="123"{
      c.String(200,"登录成功!")
   }else{
      c.String(200,"用户名或者密码错误!")
   }
}

func article(c *gin.Context)  {
   y:=c.Param("year")
   m:=c.Param("month")
   fmt.Println(y+" "+m)
   c.String(200,y+" "+m)
}

func main() {
   r:=gin.Default()
   r.LoadHTMLGlob("templates/*")
   r.Any("/test",test)
   r.GET("/login",loginHtml)
   r.POST("/login",loginAuth)
   r.GET("/article/:year/:month",article)
   _=r.Run()
}

 

 

 

 

 

练习

package main

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

func test(c *gin.Context){
   fmt.Println("test...")
   c.String(http.StatusOK,"hello world!")
}
func loginHtml(c *gin.Context){
   c.HTML(200,"login.html",nil)
}
func loginAuth(c *gin.Context){
   user:=c.PostForm("user")
   pwd:=c.PostForm("pwd")
   fmt.Println(user)
   fmt.Println(pwd)
   if user== "user1" && pwd=="123" {
      c.String(200,"登录成功")
   }else{
      c.String(200,"登录失败")
   }
}
func article(c *gin.Context) {
   y:=c.Param("year")
   m:=c.Param("month")
   c.String(200,y+" "+m)
}

func main() {
   r:=gin.Default()
   r.LoadHTMLGlob("template/*")
   r.Any("/test",test)
   r.GET("/login",loginHtml)
   r.POST("/login",loginAuth)
   r.GET("/article/:year/:month",article)
   r.Run()
}

 

 

 

下午3 shouldbind函数

基于请求的Content-Type识别请求数据类型并利用反射机制自动提取请求中querystring、form表单、JSON、XML等类型的数据,绑定到指定的结构体对象

package main

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

type User struct {
   Name string `json:"name" form:"name"`
   Email string `json:"email" form:"email"`
}

func sb(c *gin.Context){
   fmt.Println(c.PostForm("name"))
   user:=User{}
   err:=c.ShouldBind(&user)
   if err!=nil{
      fmt.Println("err",err)
   }
   fmt.Println(user)
   fmt.Println(user.Name)
   fmt.Println(user.Email)
   c.String(200,"OK")
}

func main() {
   r:=gin.Default()
   r.POST("/shouldBind",sb)
   _=r.Run()
}

 

发送json类型验证

 

 

 

发送urlencoded类型验证

 

postform只能接收urlencoded数据

 

 

 

下午4 09 gin框架的响应方式

1 响应字符串

package main

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

func getStr(c *gin.Context){
   c.String(200,"hello string!")
}

func main() {
   r:=gin.Default()
   r.GET("/str",getStr)
   _=r.Run()
}

 

 

 

2 响应html页面

demo\templates\index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h3>这是一个首页页面</h3>
</body>
</html>

 

demo\main.go

package main

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

func getStr(c *gin.Context){
   c.String(200,"hello string!")
}

func getHtml(c *gin.Context){
   c.HTML(200,"index.html",nil)
}

func main() {
   r:=gin.Default()
   r.LoadHTMLGlob("templates/*")
   r.GET("/str",getStr)
   r.GET("/html",getHtml)
   _=r.Run()
}

 

 

3 响应json

demo\main.go

package main

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

func getStr(c *gin.Context){
   c.String(200,"hello string!")
}

func getHtml(c *gin.Context){
   c.HTML(200,"index.html",nil)
}

func getJson(c *gin.Context)  {
   c.JSON(200,gin.H{
      "name":"user01",
      "age":18,
   })
}

func main() {
   r:=gin.Default()
   r.LoadHTMLGlob("templates/*")
   r.GET("/str",getStr)
   r.GET("/html",getHtml)
   r.GET("/json",getJson)
   _=r.Run()
}

 

 

 

 

Content-Type: application/json; charset=utf-8

 

 

4 响应xml

package main

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

func getStr(c *gin.Context){
   c.String(200,"hello string!")
}

func getHtml(c *gin.Context){
   c.HTML(200,"index.html",nil)
}

func getJson(c *gin.Context)  {
   c.JSON(200,gin.H{
      "name":"user01",
      "age":18,
   })
}
func getXml(c *gin.Context)  {
   c.XML(200,gin.H{
      "name":"user01",
      "age":18,
   })
}

func main() {
   r:=gin.Default()
   r.LoadHTMLGlob("templates/*")
   r.GET("/str",getStr)
   r.GET("/html",getHtml)
   r.GET("/json",getJson)
   r.GET("/xml",getXml)
   _=r.Run()
}

 

 

Content-Type: application/xml; charset=utf-8

 

 

 

 

 

响应protobuf格式(未测试,待补充)

func getProtobuf(c *gin.Context){
   //c.YAML(http.StatusOK, gin.H{"message":"消息"})
   reps := []int64{int64(9),int64(55)}

   // 自定义数据
   label := "你好啊,今天天气挺好的"

   // 传protobuf格式数据
   data := &protoexample.Test{
      Label: &label,
      Reps: reps,
   }
   fmt.Println(data)
   c.ProtoBuf(200,data)
}

 

练习

package main

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

func getStr(c *gin.Context){
   c.String(200,"hello")
}

func getHtml(c *gin.Context){
   c.HTML(200,"index.html",nil)
}
func getJson(c *gin.Context){
   c.JSON(200,gin.H{
      "name":"user1",
      "age":22,
   })
}
func getXml(c *gin.Context){
   c.XML(200,gin.H{
      "name":"user2",
      "age":18,
   })
}

func main() {
   r:=gin.Default()
   r.LoadHTMLGlob("template/*")
   r.GET("/str",getStr)
   r.GET("/html",getHtml)
   r.GET("/json",getJson)
   r.GET("/xml",getXml)
   _ = r.Run()
}

 

下午5 静态文件

让浏览器访问请求直接能访问到静态文件 css 和js等

示例1

demo\templates\index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
<!--   <link rel="stylesheet" href="/static/common.css">-->
<!--    <script src="static/index.js"></script>-->
    <style>
        h3{
            text-align: center;
            color: red;
        }
    </style>
    <script>
        alert(123)
    </script>
</head>
<body>
<h3>这是一个首页页面</h3>
</body>
</html>

demo\main.go

package main

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

func getHtml(c *gin.Context){
   c.HTML(200,"index.html",nil)
}


func main() {
   r:=gin.Default()
   r.LoadHTMLGlob("templates/*")
   r.GET("/html",getHtml)
   _=r.Run()
}

测试访问

 

示例2

1 修改静态文件

修改静态文件

 

demo\statics\common.css

h3{
    text-align: center;
}

demo\statics\index.js

window.onload=function (){
    dom=document.querySelector("h3")
    dom.onclick=function(){
        this.style.color="green"
    }
}

demo\templates\index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/common.css">
    <script src="static/index.js"></script>
</head>
<body>
<h3>这是一个首页页面</h3>
</body>
</html>

2修改main.go 增加Static

demo\main.go

package main

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

func getHtml(c *gin.Context){
   c.HTML(200,"index.html",nil)
}


func main() {
   r:=gin.Default()
   r.LoadHTMLGlob("templates/*")
   r.Static("/static","statics")
   r.GET("/html",getHtml)
   _=r.Run()
}

3 测试访问到静态资源

http://127.0.0.1:8080/static/common.css

 

3.2 测试访问

测试访问http://127.0.0.1:8080/html,点击页面变绿色

 

正常1个请求1个响应

 

发送三个请求

 

 

下午6 重定向

c.Redirect(http.StatusFound,"https://www.baidu.com")

 

demo\main.go

package main

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

func getHtml(c *gin.Context){
   c.HTML(200,"index.html",nil)
}

func  getRedirect(c *gin.Context)  {
   c.Redirect(http.StatusFound,"https://www.baidu.com")
}


func main() {
   r:=gin.Default()
   r.LoadHTMLGlob("templates/*")
   r.Static("/static","statics")
   r.GET("/html",getHtml)
   r.GET("/redirect",getRedirect)
   _=r.Run()
}

 

 

 

 

 

 

站内重定向

 c.Redirect(http.StatusFound,"/html")

 

package main

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

func getHtml(c *gin.Context){
   c.HTML(200,"index.html",nil)
}

func  getRedirect(c *gin.Context)  {
   c.Redirect(http.StatusFound,"/html")
}


func main() {
   r:=gin.Default()
   r.LoadHTMLGlob("templates/*")
   r.Static("/static","statics")
   r.GET("/html",getHtml)
   r.GET("/redirect",getRedirect)
   _=r.Run()
}

 

标签:200,func,GET,Day16,Context,test,gin
来源: https://www.cnblogs.com/zhutao2014/p/16215034.html