In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-26 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article mainly explains "how to master compilation template / custom structure binding / http2/ operation Cookie", the article explains the content is simple and clear, easy to learn and understand, the following please follow the editor's ideas slowly in depth, together to study and learn "how to master compilation template / custom structure binding / http2/ operation Cookie" bar!
Compile the template file together into a single binary file
With go-assets, you can compile the template file and the service into a binary single file, and you can deploy the service quickly and easily. Please refer to the go asset compiler go-assets-builder
How to use it:
1. Download the dependency package go get github.com/gin-gonic/gin go get github.com/jessevdk/go-assets-builder 2. Generate the html folder (containing the html code) as the go asset file assets.go go-assets-builder html-o assets.go 3. 0. Compile and build, package the service as a single binary file go build-o assets-in-binary 4. 0. Run the service. / assets-in-binary
The reference content of go asset file go-assets.go is as follows:
Package main import ("time"github.com/jessevdk/go-assets") var _ Assetsbfa8d115ce0617d89507412d5393a462f8e9b003 = "\ n\ n
Can you see this? → {{.Bar}}
\ n\ n "var _ Assets3737a75b5254ed1f6d588b40a3449721f9ea86c2 ="\ n\ n
Hello, {{.Foo}}
\ n\ n "/ / Assets returns go-assets FileSystem var Assets = assets.NewFileSystem (map [string] [] string {" / ": {" html "}," / html ": {" bar.tmpl "," index.tmpl "}}, map [string] * assets.File {" / ": {Path:" / ", FileMode: 0x800001ed, Mtime: time.Unix (1524365738, 1524365738517125470), Data: nil,} "/ html": {Path: "/ html", FileMode: 0x800001ed, Mtime: time.Unix (1524365491, 1524365491289799093), Data: nil,}, "/ html/bar.tmpl": {Path: "/ html/bar.tmpl", FileMode: 0x1a4, Mtime: time.Unix (1524365491,1524365491289611557), Data: [] byte (_ Assetsbfa8d115ce0617d89507412d5393a462f8e9b003),} "/ html/index.tmpl": {Path: "/ html/index.tmpl", FileMode: 0x1a4, Mtime: time.Unix (1524365491, 1524365491289995821), Data: [] byte (_ Assets3737a75b5254ed1f6d588b40a3449721f9ea86c2),}}, "")
Main.go
Package main import ("github.com/gin-gonic/gin"io/ioutil"net/http"strings"html/template") func main () {r: = gin.New () t, err: = loadTemplate () / / load the template generated by go-assets-builder if err! = nil {panic (err)} r.SetHTMLTemplate (t) r.GET ("/") Func (c * gin.Context) {c.HTML (http.StatusOK, "/ html/index.tmpl", nil)}) r.Run (": 8080")} / / loadTemplate loads templates embedded by go-assets-builder / / load the asset file generated by go-assets-builder and return the address of the template func loadTemplate () (* template.Template, error) {t: = template.New (") for name File: = range Assets.Files {defer file.Close () if file.IsDir () | |! strings.HasSuffix (name, ".tmpl") {/ / Skip directories or files without .tmpl suffix continue} h, err: = ioutil.ReadAll (file) if err! = nil {return nil, err} t, err = t.New (name) .Parse (string (h)) / / create a new template The file name is the template name, and the file content is the template content if err! = nil {return nil, err}} return t, nil}
For a complete example, please see this directory.
Use a custom structure to bind the request form
Refer to the example code:
Type StructA struct {FieldA string `form: "field_a" `} type StructB struct {NestedStruct StructA FieldB string `form: "field_b"`} type StructC struct {NestedStructPointer * StructA FieldC string `form: "field_c" `} type StructD struct {NestedAnonyStruct struct {FieldX string `form: "field_x"`} FieldD string `form: "field_d" `} func GetDataB (c * gin.Context) {var b StructB C.Bind (& b) c.JSON Gin.H {"a": b.NestedStruct, "b": b.FieldB,})} func GetDataC (c * gin.Context) {var b StructC c.Bind (& b) c.JSON, gin.H {"a": b.NestedStructPointer, "c": b.FieldC })} func GetDataD (c * gin.Context) {var b StructD c.Bind (& b) c.JSON, gin.H {"x": b.NestedAnonyStruct, "d": b.FieldD,})} func main () {r: = gin.Default () r.GET ("/ getb", GetDataB) r.GET ("/ getc", GetDataC) r.GET ("/ getd") GetDataD) r.Run ()}
Use the command curl to simulate the request test and the results are as follows:
$curl "http://localhost:8080/getb?field_a=hello&field_b=world" {" a ": {" FieldA ":" hello "}," b ":" world "} $curl" http://localhost:8080/getc?field_a=hello&field_c=world" {"a": {"FieldA": "hello"}, "c": "world"} $curl "http://localhost:8080/getd?field_x=hello&field_d=world" {" d ":" world " "x": {"FieldX": "hello"}}
Try to bind the request body to a different structure
The regular method binding request body is to call c.Request.Body, but it cannot be called multiple times
Type formA struct {Foo string `json: "foo" xml: "foo" binding: "required" `} type formB struct {Bar string `json: "bar" xml: "bar" binding: "required"`} func SomeHandler (c * gin.Context) {objA: = formA {} objB: = formB {} / / This c.ShouldBind consumes c.Request.Body and it cannot be reused. / / consume c.Request.Body using c.ShoudBind, but it can only call if errA once: = c.ShouldBind (& objA); errA = = nil {c.String (http.StatusOK, `the body should be formA`) / / Always an error is occurred by this because c.Request.Body is EOF now. / / an error will be reported here because c.Request.Body has been consumed and the file Terminator EOF} else if errB: = c.ShouldBind (& objB) will be returned; errB = = nil {c.String (http.StatusOK, `the body should be formB`)} else {...}}
To solve this problem, you can use the c.ShouldBindBodyWith method.
Func SomeHandler (c * gin.Context) {objA: = formA {} objB: = formB {} / / This reads c.Request.Body and stores the result into the context. / / the c.ShouldBindBodyWith method reads c.Request.Body and stores the result in the context if errA: = c.ShouldBindBodyWith (& objA, binding.JSON); errA = = nil {c.String (http.StatusOK, `the body should be formA`) / / At this time, it reuses body stored in the context. / / when c.ShouldBindBodyWith is called again, the request body content can be reused from the context} else if errB: = c.ShouldBindBodyWith (& objB, binding.JSON); errB = = nil {c.String (http.StatusOK, `the body should be formB JSON`) / / And it can accepts other formats can also accept other types of binding, such as XML} else if errB2: = c.ShouldBindBodyWith (& objB, binding.XML) ErrB2 = = nil {c.String (http.StatusOK, `the body should be formB XML`)} else {...}}
C.ShouldBindBodyWith this method stores the request body in the gin context before binding, so this has a slight impact on performance, so if you plan to bind only once, you should not use this method.
This method only supports the following formats: JSON, XML, MsgPack,ProtoBuf. For other formats, Query, Form, FormPost, FormMultipart, you can reuse the c.ShouldBind () method without similar performance impact, as detailed in (# 1341)
Http2 service push
In order to solve the problems of low utilization of network resources and delay in HTTP/1.X, HTTP/2 introduces server push mechanism to solve these problems.
Http.Pusher requires go1.8+ version support. See the golang blog for details.
Package main import ("html/template"log"github.com/gin-gonic/gin") / / define the html template var html = template.Must (template.New ("https") .Parse (`Https Test Welcome, Ginner! `) func main () {r: = gin.Default () r.Static ("/ assets", ". / assets") r.SetHTMLTemplate (html) r.GET ("/") Func (c * gin.Context) {if pusher: = c.Writer.Pusher () Pusher! = nil {/ / get the pusher / / use pusher.Push () to do server push / / use the pusher.Push () method to perform the server push action and try to push the app.js file if err: = pusher.Push ("/ assets/app.js", nil) Err! = nil {log.Printf ("Failed to push:% v", err)}} c.HTML (200, "https", gin.H {"status": "success",})) / / Listen and Server in https://127.0.0.1:8080 r.RunTLS (": 8080", ". / testdata/server.pem", ". / testdata/server.key")}
Define the routing log format
The default route log is as follows:
[GIN-debug] POST / foo-> main.main.func1 (3 handlers) [GIN-debug] GET / bar-> main.main.func2 (3 handlers) [GIN-debug] GET / status-> main.main.func3 (3 handlers)
If you want to record routing logs in a given format (such as JSON, key-value equivalence), you can use the gin.DebugPrintRouteFunc method to customize the log format. In the following example, we use the log log standard library to record router logs. Of course, you can also use other business-appropriate logging tools.
Package main import ("log"net/http"github.com/gin-gonic/gin") func main () {r: = gin.Default () / use DebugPrintRouteFunc to set the route log format. Here, the standard library log package is used to record the request method / request path / controller name / number of controller chains, gin.DebugPrintRouteFunc = func (httpMethod, absolutePath, handlerName string) NuHandlers int) {log.Printf ("endpoint% v% v% v\ n", httpMethod, absolutePath, handlerName, nuHandlers)} r.POST ("/ foo", func (c * gin.Context) {c.JSON (http.StatusOK, "foo")}) r.GET ("/ bar", func (c * gin.Context) {c.JSON (http.StatusOK, "bar")}) r.GET ("/ status") Func (c * gin.Context) {c.JSON (http.StatusOK, "ok")}) / / Listen and Server in http://0.0.0.0:8080 r.Run ()}
Set up and read Cookie
Import ("fmt"github.com/gin-gonic/gin") func main () {router: = gin.Default () router.GET ("/ cookie", func (c * gin.Context) {/ / read Cookie cookie Err: = c.Cookie ("gin_cookie") if err! = nil {cookie = "NotSet" / / set Cookie c.SetCookie ("gin_cookie", "test", 3600, "/", "localhost", false, true)} fmt.Printf ("Cookie value:% s\ n", cookie)}) router.Run ()}
test
It is recommended to use the net/http/httptest package for HTTP testing.
Package main func setupRouter () * gin.Engine {r: = gin.Default () r.GET ("/ ping", func (c * gin.Context) {c.String (200," pong ")}) return r} func main () {r: = setupRouter () r.Run (": 8080 ")}
Test code example:
Package main import ("net/http"net/http/httptest"testing"github.com/stretchr/testify/assert") func TestPingRoute (t * testing.T) {router: = setupRouter () w: = httptest.NewRecorder () req, _: = http.NewRequest ("GET", "/ ping", nil) router.ServeHTTP (w, req) / / assertion assert.Equal (t, 200, w.Code) assert.Equal (t "pong", w.Body.String ()}
Gin framework users
Other high-quality projects also use the GinWeb framework.
Gorush: a push Notification system implemented with GO
Fnproject: a cross-cloud platform with native containerization and no service
Photoprism: personal photo management supported by Go and Google's TensorFlow framework
Krakend: the extreme High performance API Gateway with Middleware
Picfit: a picture editing server implemented with Go
Brigade: event-driven scripts for Kubernetes services
Dkron: a distributed and reliable task scheduling system
Thank you for reading, the above is "how to master compilation template / custom structure binding / http2/ operation Cookie" content, after the study of this article, I believe you on how to master compilation template / custom structure binding / http2/ operation Cookie this problem has a deeper understanding, the specific use of the situation also needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.