当前位置:首页 » 《随便一记》 » 正文

Go Web 开发

28 人参与  2024年02月16日 11:21  分类 : 《随便一记》  评论

点击全文阅读


第一个Go Web 程序

package mainimport ("fmt""net/http")func hello(w http.ResponseWriter, r *http.Request) {fmt.Fprintf(w, "hello world")}func main() {server := &http.Server{Addr: "127.0.0.1:8080",}http.HandleFunc("/", hello)server.ListenAndServe()}

跑起来的效果:
在这里插入图片描述

Gin框架的使用

gin示例

package mainimport ("github.com/gin-gonic/gin""net/http")func main() {//创建一个默认的路由引擎r := gin.Default()// GET:请求方式;/hello:请求的路径// 当客户端以GET方法请求/hello路径时,会执行后面的匿名函数r.GET("/hello", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "hello go",})})r.Run()}

RESTful API(后面会用go实现)

REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”或“表现层状态转化”。
简单来说,REST的含义就是客户端与Web服务器之间进行交互的时候,使用HTTP协议中的4个请求方法代表不同的动作。

GET用来获取资源POST用来新建资源PUT用来更新资源DELETE用来删除资源
只要API程序遵循了REST风格,那就可以称其为RESTful API。目前在前后端分离的架构中,前后端基本都是通过RESTful API来进行交互。

Gin框架支持RESTful API的开发。
示例:

package mainimport "github.com/gin-gonic/gin"func main() {r := gin.Default()r.GET("/book", func(c *gin.Context) {c.JSON(200, gin.H{"message": "GET",})})r.POST("/book", func(c *gin.Context) {c.JSON(200, gin.H{"message": "POST",})})r.DELETE("/book", func(c *gin.Context) {c.JSON(200, gin.H{"message": "DELETE",})})r.PUT("/book", func(c *gin.Context) {c.JSON(200, gin.H{"message": "PUT",})})r.Run()}

搭配Postman使用

template 初识

在下面的代码片段里面涉及到了 如何 自定义模版函数 加载静态模版 的方法:

package mainimport (   "github.com/gin-gonic/gin"   "html/template"   "net/http")//自定义模版函数func main() {   r := gin.Default()   //加载静态模板   r.Static("/xxx", "./statics")   //自定义模版函数   r.SetFuncMap(template.FuncMap{   "safe": func(str string) template.HTML {   return template.HTML(str)   },   })   //加载模版   r.LoadHTMLGlob("templates/*")   r.GET("/index", func(c *gin.Context) {   c.HTML(http.StatusOK, "index.html", "<a href='https://yoboot.github.io'>小王的bolg</a>")   })   r.Run(":9090")}
//文件路径:templates/*<!doctype html><html lang="en"><head>    <meta charset="UTF-8">    <meta name="viewport"          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">    <meta http-equiv="X-UA-Compatible" content="ie=edge">    <title>Document</title></head><body><div>{{ . | safe }}</div></body></html>

JSON渲染

package mainimport (   "github.com/gin-gonic/gin"   "net/http")func main() {   r := gin.Default()   //1gin.H 是map[string]interface{}的缩写   r.GET("/index", func(c *gin.Context) {   c.JSON(http.StatusOK, gin.H{"小王": 18, "牛魔王": "我卡拉卡"})   })      type msg struct {   Name string `json:"name"`   Age  int `json:"age"`   }   r.GET("/msg", func(c *gin.Context) {   data := msg{   Age:  18,   Name: "小王子",   }   //2.使用结构体   c.JSON(http.StatusOK, data)   })   r.Run()}

获取参数

获取querystring参数

querystring 指的是URL中?后面携带的参数,例如:
/user/search?username=小王子&address=沙河。
获取请求的querystring参数的方法如下:

package mainimport (   "github.com/gin-gonic/gin"   "net/http")func main() {   //querystring   r := gin.Default()   r.GET("/web", func(c *gin.Context) {   // http://localhost:8080/web?query=小王   //获取浏览器那边发送请求携带的参数 query string 参数   //name := c.Query("query") //通过Query获取请求中携带的querystring参数   //name, ok := c.GetQuery("query") //通过GetQuery获取参数,获取不到第二个参数返回bool值   //if !ok {   ////获取不到   //name = "sombody"   //}   name := c.DefaultQuery("query", "sombody") //通过DefaultQuery获取参数,获取不到返回默认值   c.JSON(http.StatusOK, name)   })   r.Run()}

获取form 参数

login.html

<!doctype html><html lang="en"><head>    <meta charset="UTF-8">    <meta name="viewport"          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">    <meta http-equiv="X-UA-Compatible" content="ie=edge">    <title>Document</title></head><body><form action="/login" method="post" novalidate autocomplete="off">    <div>        <label for="username">username:</label>        <input type="text" name="username" id="username">    </div>    <div>        <label for="password">password</label>        <input type="password" name="password" id="password">    </div>    <div>        <input type="submit" value="登录">    </div></form></body></html>

index.html

<!doctype html><html lang="en"><head>    <meta charset="UTF-8">    <meta name="viewport"          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">    <meta http-equiv="X-UA-Compatible" content="ie=edge">    <title>Document</title></head><body><h1>Hello,{{.Name}}</h1><p>你的密码是:{{.Password}}</p></body></html>
package mainimport (   "github.com/gin-gonic/gin"   "net/http")func main() {   r := gin.Default()   r.LoadHTMLFiles("./login.html", "./index.html")   r.GET("/login", func(c *gin.Context) {   c.HTML(http.StatusOK, "login.html", nil)   })   //login post   r.POST("/login", func(c *gin.Context) {   //第一种获取form表单提交数据的方法 PostForm   /*username := c.PostForm("username")   password := c.PostForm("password")   */   //第二种获取form表单提交数据的方法 DefaultPostForm   // DefaultPostForm 找不到数据返回默认值,值得注意的是这里说的是你提交的参数找不到      /*username := c.DefaultPostForm("username", "somebody")   password := c.DefaultPostForm("password", "0000")   */      //第三种获取方法 GetPostForm 获取不到则返回bool值   username, ok := c.GetPostForm("username")   if !ok {   username = "somebody"   }   password, ok := c.GetPostForm("password")   if !ok {   password = "0000"   }   c.HTML(200, "index.html", gin.H{   "Name":     username,   "Password": password,   })   })   r.Run()}

获取URL路径参数

http://localhost:8080/user/小王/庆阳

package mainimport "github.com/gin-gonic/gin"func main() {r := gin.Default()r.GET("/user/:username/:address", func(c *gin.Context) {// Param 获取path参数username := c.Param("username")address := c.Param("address")c.JSON(200, gin.H{"message":  "ok","username": username,"address":  address,})})r.Run()}

执行结果:
{“address”:“庆阳”,“message”:“ok”,“username”:“小王”}

参数绑定

为了能够更方便的获取请求相关参数,提高开发效率,我们可以基于请求的Content-Type识别请求数据类型并利用反射机制自动提取请求中QueryString、form表单、JSON、XML等参数到结构体中。 下面的示例代码演示了.ShouldBind()强大的功能,它能够基于请求自动提取JSON、form表单和QueryString类型的数据,并把值绑定到指定的结构体对象。
inde.html:

<!doctype html><html lang="en"><head>   <meta charset="UTF-8">   <meta name="viewport"         content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">   <meta http-equiv="X-UA-Compatible" content="ie=edge">   <title>index</title></head><body><form action="/form" method="post">   用户名:   <input type="text" name="username">   密码:   <input type="password" name="password">   <input type="submit" value="提交"></form></body></html>
package mainimport (   "fmt"   "github.com/gin-gonic/gin"   "net/http")type UserInfo struct {   Username string `form:"username"`   Password string `form:"password"`}func main() {   r := gin.Default()   r.LoadHTMLFiles("./index.html")   r.GET("/user", func(c *gin.Context) {   u := UserInfo{}   /*u.Username = c.Query("username")   u.Password = c.Query("password")*/   //与上面相比ShouldBind()展示了它的强大之处   err := c.ShouldBind(&u)   if err != nil {   c.JSON(http.StatusBadGateway, gin.H{   "err": err.Error(),   })   } else {   fmt.Println(u)   c.JSON(200, gin.H{   "message": "ok",   })   }   })   r.GET("/index", func(c *gin.Context) {   c.HTML(200, "index.html", nil)   })   r.POST("/form", func(c *gin.Context) {   u := UserInfo{}   err := c.ShouldBind(&u)   if err != nil {   c.JSON(http.StatusBadGateway, gin.H{   "err": err.Error(),   })   } else {   fmt.Println(u)   c.JSON(200, gin.H{   "message": "ok",   })   }   })   //与postman搭配   r.POST("/json", func(c *gin.Context) {   u := UserInfo{}   err := c.ShouldBind(&u)   if err != nil {   c.JSON(http.StatusBadGateway, gin.H{   "err": err.Error(),   })   } else {   fmt.Println(u)   c.JSON(200, gin.H{   "message": "ok",   })   }   })   r.Run()}

文件上传

通过网络将本地文件从客户端上传到服务端
单个文件上传
前端代码:

<!DOCTYPE html><html lang="zh-CN"><head>    <title>上传文件示例</title></head><body><form action="/upload" method="post" enctype="multipart/form-data">    <input type="file" name="f1">    <input type="submit" value="上传"></form></body></html>

后端gin代码

package mainimport (   "github.com/gin-gonic/gin"   "net/http"   "path")func main() {   r := gin.Default()   r.LoadHTMLFiles("./index.html")   r.GET("/index", func(c *gin.Context) {   c.HTML(200, "index.html", nil)   })   r.POST("/upload", func(c *gin.Context) {   //从请求中读取文件   f, err := c.FormFile("f1")   if err != nil {   c.JSON(http.StatusBadGateway, gin.H{   "error": err.Error(),   })   } else {   //将读取到的文件保存到本地(服务器)   //dst := fmt.Sprint("./%s", f.Filename)   dst := path.Join("./", f.Filename)   //上传文件到指定目录   c.SaveUploadedFile(f, dst)   c.JSON(200, gin.H{   "message": "ok",   })   }   })   r.Run()}

多个文件上传

func main() {router := gin.Default()// 处理multipart forms提交文件时默认的内存限制是32 MiB// 可以通过下面的方式修改// router.MaxMultipartMemory = 8 << 20  // 8 MiBrouter.POST("/upload", func(c *gin.Context) {// Multipart formform, _ := c.MultipartForm()files := form.File["file"]for index, file := range files {log.Println(file.Filename)dst := fmt.Sprintf("C:/tmp/%s_%d", file.Filename, index)// 上传文件到指定的目录c.SaveUploadedFile(file, dst)}c.JSON(http.StatusOK, gin.H{"message": fmt.Sprintf("%d files uploaded!", len(files)),})})router.Run()}

HTTP重定向

r.GET("/test", func(c *gin.Context) {c.Redirect(http.StatusMovedPermanently, "http://www.sogo.com/")})

路由重定向

路由重定向,使用HandleContext:

package mainimport ("github.com/gin-gonic/gin""net/http")func main() {r := gin.Default()r.GET("/a", func(c *gin.Context) {c.Request.URL.Path = "/b"r.HandleContext(c)})r.GET("/b", func(c *gin.Context) {c.JSON(200, gin.H{"message": "Yoboot",})})r.Run()}

路由组

这里先介绍两个路由 Any 和 NoRoute
一个可以匹配所有请求方法的Any:

r.Any("./index", func(c *gin.Context) {   switch c.Request.Method {   case http.MethodGet:   c.JSON(200, gin.H{"message": "index get"})   case http.MethodPut:   c.JSON(200, gin.H{"message": "index put"})   case http.MethodPost:   c.JSON(200, gin.H{"message": "index post"})   }   })   ```NoRoute  为没有配置处理函数的路由添加处理程序,默认情况下它返回404代码```go//NoRoute 没有定义的路由   r.NoRoute(func(c *gin.Context) {   c.JSON(http.StatusNotFound, gin.H{"msg": "此路由没有定义"})   })

路由组

//把公用的前缀提取出来,创建一个路由组videoGroup := r.Group("/video"){videoGroup.GET("/index", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"msg": "/video/index"})})videoGroup.GET("/xx", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"msg": "/video/xx"})})videoGroup.GET("/oo", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"msg": "/video/oo"})})}

点击全文阅读


本文链接:http://zhangshiyu.com/post/68655.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1