一、html渲染
-
使用 LoadHTMLGlob()
-
package main import ( "github.com/gin-gonic/gin" "net/http" ) func main() { r := gin.Default() r.LoadHTMLGlob("static/templates/*") r.GET("/", func(c *gin.Context) { c.HTML(http.StatusOK, "index.html", gin.H{"title": "golang web"}) }) r.Run(":8000") }
-
static/templates/index.html <html> <h1> {{ .title }} </h1> </html>
二、表单绑定
-
package main import ( "github.com/gin-gonic/gin" "github.com/gin-gonic/gin/binding" ) type LoginForm struct { User string `form:"user" binding:"required"` Password string `form:"password" binding:"required"` } func main() { r := gin.Default() r.POST("/login", func(c *gin.Context) { // 你可以使用显式绑定声明绑定 multipart form: // c.ShouldBindWith(&form, binding.Form) // 或者简单地使用 ShouldBind 方法自动绑定: var form LoginForm // 在这种情况下,将自动选择合适的绑定 if c.ShouldBindWith(&form, binding.Form) == nil { if form.User == "user" && form.Password == "password" { c.JSON(200, gin.H{"status": "you are logged in"}) } else { c.JSON(401, gin.H{"status": "unauthorized"}) } } }) r.Run(":8000") } /** * Trying 127.0.0.1:8000... * Connected to localhost (127.0.0.1) port 8000 (#0) > POST /login HTTP/1.1 > Host: localhost:8000 > User-Agent: curl/7.83.1 > Accept: */* > Content-Length: 248 > Content-Type: multipart/form-data; boundary=------------------------e350eab01c4dd2e0 > * We are completely uploaded and fine * Mark bundle as not supporting multiuse < HTTP/1.1 200 OK < Content-Type: application/json; charset=utf-8 < Date: Mon, 24 Oct 2022 04:28:05 GMT < Content-Length: 30 < {"status":"you are logged in"}* Connection #0 to host localhost left intact */
三、xml/json/yaml/protobuf渲染
-
package main import ( "github.com/gin-gonic/gin" "github.com/gin-gonic/gin/testdata/protoexample" "net/http" ) type message struct { Code int `json:"code"` Msg string `json:"msg"` Data string `json:"data"` } func main() { r := gin.Default() r.GET("/json", func(c *gin.Context) { c.SecureJSON(200, message{ Code: 200, Msg: "成功", Data: "{\"name\":\"小哥\"}", }) }) r.GET("/xml", func(c *gin.Context) { c.XML(http.StatusOK, gin.H{"message": "xml", "status": http.StatusOK}) }) r.GET("/yaml", func(c *gin.Context) { c.YAML(http.StatusOK, gin.H{"message": "yaml", "status": http.StatusOK}) }) r.GET("/protobuf", func(c *gin.Context) { reps := []int64{int64(1), int64(2)} label := "test" // protobuf 的具体定义写在 testdata/protoexample 文件中。 data := &protoexample.Test{ Label: &label, Reps: reps, } // 请注意,数据在响应中变为二进制数据 c.ProtoBuf(http.StatusOK, data) }) r.Run(":8000") }
四、文件上传
-
package main import ( "fmt" "github.com/gin-gonic/gin" "log" "net/http" ) func main() { r := gin.Default() r.MaxMultipartMemory = 8 << 20 // 8 MiB r.POST("/upload", func(c *gin.Context) { form, _ := c.MultipartForm() files := form.File["upload[]"] for _, file := range files { log.Println(file.Filename) dst := "./" + file.Filename // 上传文件至指定目录 c.SaveUploadedFile(file, dst) } c.String(http.StatusOK, fmt.Sprintf("%d files uploaded!", len(files))) }) r.Run(":8000") /** curl -X POST http://localhost:8000/upload -F "upload[]=@./X_80.png" -H "Content-Type: multipart/form-data" */ }
五、从reader读取器中读取
-
package main import ( "github.com/gin-gonic/gin" "net/http" ) func main() { r := gin.Default() r.GET("/someDataFromReader", func(c *gin.Context) { response, err := http.Get("https://www.linuxprobe.com/wp-content/uploads/2022/05/00SLU5M6ZFYOXWK_E2.png") if err != nil || response.StatusCode != http.StatusOK { c.Status(http.StatusServiceUnavailable) return } reader := response.Body contentLength := response.ContentLength contentType := response.Header.Get("Content-Type") extraHeaders := map[string]string{ "Content-Disposition": `attachment; filename="gopher.png"`, } c.DataFromReader(http.StatusOK, contentLength, contentType, reader, extraHeaders) }) r.Run(":8000") }
六、优雅的关闭服务器
-
package main import ( "context" "github.com/gin-gonic/gin" "log" "net/http" "os" "os/signal" "time" ) func main() { r := gin.Default() r.GET("/someDataFromReader", func(c *gin.Context) { response, err := http.Get("https://www.linuxprobe.com/wp-content/uploads/2022/05/00SLU5M6ZFYOXWK_E2.png") if err != nil || response.StatusCode != http.StatusOK { c.Status(http.StatusServiceUnavailable) return } reader := response.Body contentLength := response.ContentLength contentType := response.Header.Get("Content-Type") extraHeaders := map[string]string{ "Content-Disposition": `attachment; filename="gopher.png"`, } c.DataFromReader(http.StatusOK, contentLength, contentType, reader, extraHeaders) }) //r.Run(":8000") serve := &http.Server{ Addr: ":8000", Handler: r, } go func() { if err := serve.ListenAndServe(); err != nil { log.Fatalf("listen:%s\n", err) } }() q := make(chan os.Signal) signal.Notify(q, os.Interrupt, os.Kill) <-q log.Println("server shutdown...") ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() if err := serve.Shutdown(ctx); err != nil { log.Fatalf("server shutdown:%s",err) } }
七、使用http restful 风格
-
package main import ( "github.com/gin-gonic/gin" "net/http" ) type message struct { Code int Msg string Data string } func main() { r := gin.Default() r.GET("/get", func(c *gin.Context) { c.JSON(http.StatusOK,message{ Code: 200, Msg: "成功", Data: "data ", }) }) r.POST("/post", func(c *gin.Context) { c.JSON(http.StatusOK,message{ Code: 200, Msg: "成功", Data: "data ", }) }) r.PUT("/put", func(c *gin.Context) { c.JSON(http.StatusOK,message{ Code: 200, Msg: "成功", Data: "data ", }) }) r.DELETE("/delete", func(c *gin.Context) { c.JSON(http.StatusOK,message{ Code: 200, Msg: "成功", Data: "data ", }) }) r.PATCH("/patch", func(c *gin.Context) { c.JSON(http.StatusOK,message{ Code: 200, Msg: "成功", Data: "data ", }) }) r.HEAD("/head", func(c *gin.Context) { c.JSON(http.StatusOK,message{ Code: 200, Msg: "成功", Data: "data ", }) }) r.OPTIONS("/option", func(c *gin.Context) { c.JSON(http.StatusOK,message{ Code: 200, Msg: "成功", Data: "data ", }) }) r.Run(":8000") }