Gin使用的相关笔记。
老规矩,我们要用Gin,那就得先去下载:
go get github.com/gin-gonic/gin
启动gin应用程序
func main() {
// 创建一个gin路由
router := gin.Default()
// 设置请求的接口地址
router.GET("/ping", ping)
router.GET("/get1", get)
router.GET("/get2/:name", get) // 通过占位符 : 指定路径参数名为 name
//router.GET("/get2/*name", get) // 通过占位符 * 指定路径参数名为 name
router.POST("/post", post)
router.PUT("/put", put)
//router.DELETE("/delete", Delete)
router.DELETE("/delete/:id", Delete) // 通过id删除数据
router.GET("/head", head)
router.POST("/file", file)
// 启动gin应用程序,设置端口号
router.Run(":7070")
}
统一的返回参数格式
// 统一的返回参数格式
type Result struct {
Code int // 统一的返回码,0 成功 -1 失败
Message string // 统一的返回信息
Data any // 统一的返回数据
}
统一的处理响应数据
// 处理响应数据
func handleRes(res *http.Response, err error) {
if err != nil {
fmt.Println("请求失败")
}
defer res.Body.Close()
b, err := io.ReadAll(res.Body)
if err != nil {
fmt.Println("获取返回数据错误", err)
return
}
fmt.Println(string(b))
}
GET 请求
发起get请求
func get请求() {
// 如果只是想对一个url发起一个get请求,不带任何头部信息,那么http.Get方法就非常适合
//http.Get("http://127.0.0.1:7070/ping")
res, err := http.Get("http://127.0.0.1:7070/get1?name=符华&password=123456")
//res, err := http.Get("http://127.0.0.1:7070/get2/符华")
handleRes(res, err)
}
接收
// get 请求,通过 ? 号拼接,或者是 url 路径参数
func get(c *gin.Context) {
fmt.Println("这里是一个get请求呀~")
// 1、get请求中,通过问号拼接传过来的参数,用 Query("参数名")
fmt.Println(c.Query("name"), c.Query("password"))
// DefaultQuery 和 Query 的区别就是多了一个默认值
//fmt.Println(c.DefaultQuery("name","默认值"), c.DefaultQuery("password","默认值"))
// 2、get请求中,url 路径参数接收,用 Param("路由中指定的参数名")
//fmt.Println(c.Param("name"))
// 使用 gin.H 返回
//c.JSON(http.StatusOK, gin.H{"code": 0, "message": "请求成功", "data": nil})
// 如果是想要用统一的自定义返回格式,需要使用 JSONP :将给定的结构体作为JSON序列化到响应体中。
c.JSONP(http.StatusOK, Result{0, "get请求成功", nil}) // 使用自定义的统一返回参数格式
}
POST 请求
发起post请求
这里 form-data 和 x-www-form-urlencoded 格式的区别大概是 form-data 可以传文件
func post请求() {
// post请求,一般有 json格式、 form-data格式 和 x-www-form-urlencoded 格式
//param := url.Values{}
//param.Add("name", "符华")
//param.Add("password", "123456")
// application/x-www-form-urlencoded
//res, err := http.PostForm("http://127.0.0.1:7070/post", param)
// application/json
params := bytes.NewBuffer([]byte(`{"name": "赤鸢", "password": "chiyuan@123456"}`))
res, err := http.Post("http://127.0.0.1:7070/post", "application/json", params)
handleRes(res, err)
}
接收
// post 请求,application/x-www-form-urlencoded、application/json
func post(c *gin.Context) {
fmt.Println("这里是一个post请求呀~")
// 1、请求类型是 application/x-www-form-urlencoded,通过 PostForm 获取
//fmt.Println(c.PostForm("name"), c.PostForm("password"))
// 将参数绑定结构体
//u := User{} // 初始化对象
//err := c.ShouldBind(&u) // 通过 ShouldBind 函数,将请求参数绑定到 struct 对象。
//if err != nil {
// c.JSONP(http.StatusOK, Result{0, "数据绑定失败", nil})
// return
//}
//fmt.Println(u)
// 2、请求类型是 application/json,通过 GetRawData 获取
//data, err := c.GetRawData()
//if err != nil {
// c.JSONP(http.StatusOK, Result{-1, "获取请求数据错误", nil}) // 使用自定义的统一返回参数格式
// return
//}
//fmt.Println(string(data))
// 将参数绑定结构体
var u User
//err := c.BindJSON(&u) // 通过 BindJSON 函数,将请求参数绑定到 struct 对象。
err := c.ShouldBindJSON(&u) // 通过 ShouldBindJSON 函数,将请求参数绑定到 struct 对象。
if err != nil {
c.JSONP(http.StatusOK, Result{0, "数据绑定失败", nil})
return
}
fmt.Println(u)
c.JSONP(http.StatusOK, Result{0, "post请求成功", nil}) // 使用自定义的统一返回参数格式
}
PUT 请求
发起put请求
func put请求() {
params := `{"name": "赤鸢", "password": "chiyuan@123456"}`
req, _ := http.NewRequest("PUT", "http://localhost:7070/put", strings.NewReader(params))
res, err := http.DefaultClient.Do(req)
handleRes(res, err)
}
接收
// put 请求,json格式
func put(c *gin.Context) {
fmt.Println("这里是一个put请求呀~")
// 将参数绑定结构体
var u User
//err := c.BindJSON(&u) // 通过 BindJSON 函数,将请求参数绑定到 struct 对象。
err := c.ShouldBindJSON(&u) // 通过 ShouldBindJSON 函数,将请求参数绑定到 struct 对象。
if err != nil {
c.JSONP(http.StatusOK, Result{0, "数据绑定失败", nil})
return
}
fmt.Println(u)
c.JSONP(http.StatusOK, Result{0, "put请求成功", nil}) // 使用自定义的统一返回参数格式
}
DELETE 请求
发起delete请求
func delete请求() {
// 批量删除,json 格式,多个id用逗号隔开
//params := `{"id": "1,2,3"}`
//req, _ := http.NewRequest("DELETE", "http://localhost:7070/delete", strings.NewReader(params))
// 单个删除,直接用路径模式
req, _ := http.NewRequest("DELETE", "http://localhost:7070/delete/1", nil)
res, err := http.DefaultClient.Do(req)
handleRes(res, err)
}
接收
// delete 请求,json格式和路径模式
func Delete(c *gin.Context) {
fmt.Println("这里是一个delete请求呀~")
// json 格式
//data, err := c.GetRawData()
//if err != nil {
// c.JSONP(http.StatusOK, Result{-1, "获取请求数据错误", nil})
// return
//}
//var j map[string]string
//err = json.Unmarshal(data, &j) // 将json字符串转为map
//if err != nil {
// fmt.Println(err)
// c.JSONP(http.StatusOK, Result{-1, "数据转换错误", nil})
// return
//}
//ids := j["id"]
//arr := strings.Split(ids, ",") // 根据逗号,将字符串分割成数组
//fmt.Println("需要删除的id", arr)
// 路径模式
fmt.Println("需要删除的id", c.Param("id"))
c.JSONP(http.StatusOK, Result{0, "delete请求成功", nil})
}
HEAD 请求头
设置head请求头
/*
Set和Add的区别:
Set:如果这一项已存在,后面的就修改已有的。
Add:如果不存在,则添加;如果已存在,就再追加一个。
*/
func head传参() {
req, _ := http.NewRequest("GET", "http://127.0.0.1:7070/head", nil)
//req.Header.Set("name", "符华")
//req.Header.Set("name", "赤鸢") // 这里会修改前面设置的name的值
//req.Header.Add("name", "云墨") // name已存在,会追加
req.Header.Add("name", "符华")
req.Header.Set("name", "炽翎") // 这里会修改前面设置的name的值
res, err := http.DefaultClient.Do(req)
handleRes(res, err)
}
接收
// 接收head请求头参数
func head(c *gin.Context) {
byteData, err := json.Marshal(c.Request.Header)
fmt.Println(string(byteData), err)
c.JSONP(http.StatusOK, Result{0, "head传参成功", nil})
}
file 文件上传
上传文件
func file上传() {
// 读取文件
file, err := os.Open("C:\\Users\\Administrator\\Desktop\\1.png")
if err != nil {
fmt.Println(err)
return
}
defer file.Close()
// 创建缓冲区,存储文件数据
bodyBuf := &bytes.Buffer{}
bodyWrite := multipart.NewWriter(bodyBuf)
// 创建文件表单字段
fileWrite, err := bodyWrite.CreateFormFile("file", "1.png")
// 将文件内容拷贝到表单字段中
_, err = io.Copy(fileWrite, file)
if err != nil {
log.Println("err")
return
}
// 必须在写入文件之后关闭 writer,以写入结尾标记
bodyWrite.Close()
// 设置 ContentType 为 multipart/form-data; boundary=
contentType := bodyWrite.FormDataContentType()
// 创建 HTTP 请求
res, err := http.Post("http://127.0.0.1:7070/file", contentType, bodyBuf)
handleRes(res, err)
}
接收
// 接收file参数
func file(c *gin.Context) {
fileHeader, err := c.FormFile("file")
if err != nil {
return
}
fmt.Println(fileHeader.Filename)
c.SaveUploadedFile(fileHeader, "upload/"+fileHeader.Filename)
c.JSONP(http.StatusOK, Result{0, "file上传成功", nil})
}
完整代码
服务端
package main
import (
"encoding/json"
"fmt"
"github.com/gin-gonic/gin"
"net/http"
)
// 统一的返回参数格式
type Result struct {
Code int // 统一的返回码,0 成功 -1 失败
Message string // 统一的返回信息
Data any // 统一的返回数据
}
// 用户结构体
type User struct {
Name string `json:"name" form:"name"`
Password string `json:"password" form:"password"`
}
func ping(c *gin.Context) {
fmt.Println("成功请求")
}
// get 请求,通过 ? 号拼接,或者是 url 路径参数
func get(c *gin.Context) {
fmt.Println("这里是一个get请求呀~")
// 1、get请求中,通过问号拼接传过来的参数,用 Query("参数名")
fmt.Println(c.Query("name"), c.Query("password"))
// DefaultQuery 和 Query 的区别就是多了一个默认值
//fmt.Println(c.DefaultQuery("name","默认值"), c.DefaultQuery("password","默认值"))
// 2、get请求中,url 路径参数接收,用 Param("路由中指定的参数名")
//fmt.Println(c.Param("name"))
// 使用 gin.H 返回
//c.JSON(http.StatusOK, gin.H{"code": 0, "message": "请求成功", "data": nil})
// 如果是想要用统一的自定义返回格式,需要使用 JSONP :将给定的结构体作为JSON序列化到响应体中。
c.JSONP(http.StatusOK, Result{0, "get请求成功", nil}) // 使用自定义的统一返回参数格式
}
// post 请求,application/x-www-form-urlencoded、application/json
func post(c *gin.Context) {
fmt.Println("这里是一个post请求呀~")
// 1、请求类型是 application/x-www-form-urlencoded,通过 PostForm 获取
//fmt.Println(c.PostForm("name"), c.PostForm("password"))
// 将参数绑定结构体
//u := User{} // 初始化对象
//err := c.ShouldBind(&u) // 通过 ShouldBind 函数,将请求参数绑定到 struct 对象。
//if err != nil {
// c.JSONP(http.StatusOK, Result{0, "数据绑定失败", nil})
// return
//}
//fmt.Println(u)
// 2、请求类型是 application/json,通过 GetRawData 获取
//data, err := c.GetRawData()
//if err != nil {
// c.JSONP(http.StatusOK, Result{-1, "获取请求数据错误", nil}) // 使用自定义的统一返回参数格式
// return
//}
//fmt.Println(string(data))
// 将参数绑定结构体
var u User
//err := c.BindJSON(&u) // 通过 BindJSON 函数,将请求参数绑定到 struct 对象。
err := c.ShouldBindJSON(&u) // 通过 ShouldBindJSON 函数,将请求参数绑定到 struct 对象。
if err != nil {
c.JSONP(http.StatusOK, Result{0, "数据绑定失败", nil})
return
}
fmt.Println(u)
c.JSONP(http.StatusOK, Result{0, "post请求成功", nil}) // 使用自定义的统一返回参数格式
}
// put 请求,json格式
func put(c *gin.Context) {
fmt.Println("这里是一个put请求呀~")
// 将参数绑定结构体
var u User
//err := c.BindJSON(&u) // 通过 BindJSON 函数,将请求参数绑定到 struct 对象。
err := c.ShouldBindJSON(&u) // 通过 ShouldBindJSON 函数,将请求参数绑定到 struct 对象。
if err != nil {
c.JSONP(http.StatusOK, Result{0, "数据绑定失败", nil})
return
}
fmt.Println(u)
c.JSONP(http.StatusOK, Result{0, "put请求成功", nil}) // 使用自定义的统一返回参数格式
}
// delete 请求,json格式和路径模式
func Delete(c *gin.Context) {
fmt.Println("这里是一个delete请求呀~")
// json 格式
//data, err := c.GetRawData()
//if err != nil {
// c.JSONP(http.StatusOK, Result{-1, "获取请求数据错误", nil})
// return
//}
//var j map[string]string
//err = json.Unmarshal(data, &j) // 将json字符串转为map
//if err != nil {
// fmt.Println(err)
// c.JSONP(http.StatusOK, Result{-1, "数据转换错误", nil})
// return
//}
//ids := j["id"]
//arr := strings.Split(ids, ",") // 根据逗号,将字符串分割成数组
//fmt.Println("需要删除的id", arr)
// 路径模式
fmt.Println("需要删除的id", c.Param("id"))
c.JSONP(http.StatusOK, Result{0, "delete请求成功", nil})
}
// 接收head请求头参数
func head(c *gin.Context) {
byteData, err := json.Marshal(c.Request.Header)
fmt.Println(string(byteData), err)
c.JSONP(http.StatusOK, Result{0, "head传参成功", nil})
}
// 接收file参数
func file(c *gin.Context) {
fileHeader, err := c.FormFile("file")
if err != nil {
return
}
fmt.Println(fileHeader.Filename)
c.SaveUploadedFile(fileHeader, "upload/"+fileHeader.Filename)
c.JSONP(http.StatusOK, Result{0, "file上传成功", nil})
}
func main() {
// 创建一个gin路由
router := gin.Default()
// 设置请求的接口地址
router.GET("/ping", ping)
router.GET("/get1", get)
router.GET("/get2/:name", get) // 通过占位符 : 指定路径参数名为 name
//router.GET("/get2/*name", get) // 通过占位符 * 指定路径参数名为 name
router.POST("/post", post)
router.PUT("/put", put)
//router.DELETE("/delete", Delete)
router.DELETE("/delete/:id", Delete) // 通过id删除数据
router.GET("/head", head)
router.POST("/file", file)
// 启动gin应用程序,设置端口号
router.Run(":7070")
}
客户端
package main
import (
"bytes"
"fmt"
"io"
"log"
"mime/multipart"
"net/http"
"os"
"strings"
)
// 处理响应数据
func handleRes(res *http.Response, err error) {
if err != nil {
fmt.Println("请求失败")
}
defer res.Body.Close()
b, err := io.ReadAll(res.Body)
if err != nil {
fmt.Println("获取返回数据错误", err)
return
}
fmt.Println(string(b))
}
func main() {
//get请求()
//post请求()
//put请求()
//delete请求()
//head传参()
//file上传()
}
func get请求() {
// 如果只是想对一个url发起一个get请求,不带任何头部信息,那么http.Get方法就非常适合
//http.Get("http://127.0.0.1:7070/ping")
res, err := http.Get("http://127.0.0.1:7070/get1?name=符华&password=123456")
//res, err := http.Get("http://127.0.0.1:7070/get2/符华")
handleRes(res, err)
}
func post请求() {
// post请求,一般有 json格式、 form-data格式 和 x-www-form-urlencoded 格式
//param := url.Values{}
//param.Add("name", "符华")
//param.Add("password", "123456")
// application/x-www-form-urlencoded
//res, err := http.PostForm("http://127.0.0.1:7070/post", param)
// application/json
params := bytes.NewBuffer([]byte(`{"name": "赤鸢", "password": "chiyuan@123456"}`))
res, err := http.Post("http://127.0.0.1:7070/post", "application/json", params)
handleRes(res, err)
}
func put请求() {
params := `{"name": "赤鸢", "password": "chiyuan@123456"}`
req, _ := http.NewRequest("PUT", "http://localhost:7070/put", strings.NewReader(params))
res, err := http.DefaultClient.Do(req)
handleRes(res, err)
}
func delete请求() {
// 批量删除,json 格式,多个id用逗号隔开
//params := `{"id": "1,2,3"}`
//req, _ := http.NewRequest("DELETE", "http://localhost:7070/delete", strings.NewReader(params))
// 单个删除,直接用路径模式
req, _ := http.NewRequest("DELETE", "http://localhost:7070/delete/1", nil)
res, err := http.DefaultClient.Do(req)
handleRes(res, err)
}
/*
Set和Add的区别:
Set:如果这一项已存在,后面的就修改已有的。
Add:如果不存在,则添加;如果已存在,就再追加一个。
*/
func head传参() {
req, _ := http.NewRequest("GET", "http://127.0.0.1:7070/head", nil)
//req.Header.Set("name", "符华")
//req.Header.Set("name", "赤鸢") // 这里会修改前面设置的name的值
//req.Header.Add("name", "云墨") // name已存在,会追加
req.Header.Add("name", "符华")
req.Header.Set("name", "炽翎") // 这里会修改前面设置的name的值
res, err := http.DefaultClient.Do(req)
handleRes(res, err)
}
func file上传() {
// 读取文件
file, err := os.Open("C:\\Users\\Administrator\\Desktop\\1.png")
if err != nil {
fmt.Println(err)
return
}
defer file.Close()
// 创建缓冲区,存储文件数据
bodyBuf := &bytes.Buffer{}
bodyWrite := multipart.NewWriter(bodyBuf)
// 创建文件表单字段
fileWrite, err := bodyWrite.CreateFormFile("file", "1.png")
// 将文件内容拷贝到表单字段中
_, err = io.Copy(fileWrite, file)
if err != nil {
log.Println("err")
return
}
// 必须在写入文件之后关闭 writer,以写入结尾标记
bodyWrite.Close()
// 设置 ContentType 为 multipart/form-data; boundary=
contentType := bodyWrite.FormDataContentType()
// 创建 HTTP 请求
res, err := http.Post("http://127.0.0.1:7070/file", contentType, bodyBuf)
handleRes(res, err)
}
ok,以上就是本篇笔记的全部内容了。