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