GitHub - gf0842wf/gin: Gin is a HTTP web framework written in Go (Golang). It features a Martini-like API with much better performance -- up to 40 times faster. If you need smashing performance, get yourself some Gin. · GitHub
You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Star0 (0)You must be signed in to star a repository
About
Gin is a HTTP web framework written in Go (Golang). It features a Martini-like API with much better performance -- up to 40 times faster. If you need smashing performance, get yourself some Gin.
Gin is a web framework written in Go (Golang). It features a martini-like API with much better performance, up to 40 times faster thanks to httprouter. If you need performance and good productivity, you will love Gin.
$ cat test.go
package main
import"github.com/gin-gonic/gin"funcmain() {
r:=gin.Default()
r.GET("/ping", func(c*gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
r.Run() // listen and server on 0.0.0.0:8080
}
(1): Total Repetitions
(2): Single Repetition Duration (ns/op)
(3): Heap Memory (B/op)
(4): Average Allocations per Repetition (allocs/op)
Gin v1. stable
Zero allocation router.
Still the fastest http router and framework. From routing to writing.
Complete suite of unit tests
Battle tested
API frozen, new releases will not break your code.
Start using it
Download and install it:
$ go get gopkg.in/gin-gonic/gin.v1
Import it in your code:
import"gopkg.in/gin-gonic/gin.v1"
(Optional) Import net/http. This is required for example if using constants such as http.StatusOK.
import"net/http"
API Examples
Using GET, POST, PUT, PATCH, DELETE and OPTIONS
funcmain() {
// Creates a gin router with default middleware:// logger and recovery (crash-free) middlewarerouter:=gin.Default()
router.GET("/someGet", getting)
router.POST("/somePost", posting)
router.PUT("/somePut", putting)
router.DELETE("/someDelete", deleting)
router.PATCH("/somePatch", patching)
router.HEAD("/someHead", head)
router.OPTIONS("/someOptions", options)
// By default it serves on :8080 unless a// PORT environment variable was defined.router.Run()
// router.Run(":3000") for a hard coded port
}
Parameters in path
funcmain() {
router:=gin.Default()
// This handler will match /user/john but will not match neither /user/ or /userrouter.GET("/user/:name", func(c*gin.Context) {
name:=c.Param("name")
c.String(http.StatusOK, "Hello %s", name)
})
// However, this one will match /user/john/ and also /user/john/send// If no other routers match /user/john, it will redirect to /user/john/router.GET("/user/:name/*action", func(c*gin.Context) {
name:=c.Param("name")
action:=c.Param("action")
message:=name+" is "+actionc.String(http.StatusOK, message)
})
router.Run(":8080")
}
Querystring parameters
funcmain() {
router:=gin.Default()
// Query string parameters are parsed using the existing underlying request object.// The request responds to a url matching: /welcome?firstname=Jane&lastname=Doerouter.GET("/welcome", func(c*gin.Context) {
firstname:=c.DefaultQuery("firstname", "Guest")
lastname:=c.Query("lastname") // shortcut for c.Request.URL.Query().Get("lastname")c.String(http.StatusOK, "Hello %s %s", firstname, lastname)
})
router.Run(":8080")
}
funcmain() {
// Creates a router without any middleware by defaultr:=gin.New()
// Global middlewarer.Use(gin.Logger())
r.Use(gin.Recovery())
// Per route middleware, you can add as many as you desire.r.GET("/benchmark", MyBenchLogger(), benchEndpoint)
// Authorization group// authorized := r.Group("/", AuthRequired())// exactly the same as:authorized:=r.Group("/")
// per group middleware! in this case we use the custom created// AuthRequired() middleware just in the "authorized" group.authorized.Use(AuthRequired())
{
authorized.POST("/login", loginEndpoint)
authorized.POST("/submit", submitEndpoint)
authorized.POST("/read", readEndpoint)
// nested grouptesting:=authorized.Group("testing")
testing.GET("/analytics", analyticsEndpoint)
}
// Listen and server on 0.0.0.0:8080r.Run(":8080")
}
Model binding and validation
To bind a request body into a type, use model binding. We currently support binding of JSON, XML and standard form values (foo=bar&boo=baz).
Note that you need to set the corresponding binding tag on all fields you want to bind. For example, when binding from JSON, set json:"fieldname".
When using the Bind-method, Gin tries to infer the binder depending on the Content-Type header. If you are sure what you are binding, you can use BindWith.
You can also specify that specific fields are required. If a field is decorated with binding:"required" and has a empty value when binding, the current request will fail with an error.
// Binding from JSONtypeLoginstruct {
Userstring`form:"user" json:"user" binding:"required"`Passwordstring`form:"password" json:"password" binding:"required"`
}
funcmain() {
router:=gin.Default()
// Example for binding JSON ({"user": "manu", "password": "123"})router.POST("/loginJSON", func(c*gin.Context) {
varjsonLoginifc.BindJSON(&json) ==nil {
ifjson.User=="manu"&&json.Password=="123" {
c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
} else {
c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
}
}
})
// Example for binding a HTML form (user=manu&password=123)router.POST("/loginForm", func(c*gin.Context) {
varformLogin// This will infer what binder to use depending on the content-type header.ifc.Bind(&form) ==nil {
ifform.User=="manu"&&form.Password=="123" {
c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
} else {
c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
}
}
})
// Listen and server on 0.0.0.0:8080router.Run(":8080")
}
###Multipart/Urlencoded binding
package main
import (
"github.com/gin-gonic/gin""github.com/gin-gonic/gin/binding"
)
typeLoginFormstruct {
Userstring`form:"user" binding:"required"`Passwordstring`form:"password" binding:"required"`
}
funcmain() {
router:=gin.Default()
router.POST("/login", func(c*gin.Context) {
// you can bind multipart form with explicit binding declaration:// c.BindWith(&form, binding.Form)// or you can simply use autobinding with Bind method:varformLoginForm// in this case proper binding will be automatically selectedifc.Bind(&form) ==nil {
ifform.User=="user"&&form.Password=="password" {
c.JSON(200, gin.H{"status": "you are logged in"})
} else {
c.JSON(401, gin.H{"status": "unauthorized"})
}
}
})
router.Run(":8080")
}
Both internal and external locations are supported.
Custom Middleware
funcLogger() gin.HandlerFunc {
returnfunc(c*gin.Context) {
t:=time.Now()
// Set example variablec.Set("example", "12345")
// before requestc.Next()
// after requestlatency:=time.Since(t)
log.Print(latency)
// access the status we are sendingstatus:=c.Writer.Status()
log.Println(status)
}
}
funcmain() {
r:=gin.New()
r.Use(Logger())
r.GET("/test", func(c*gin.Context) {
example:=c.MustGet("example").(string)
// it would print: "12345"log.Println(example)
})
// Listen and server on 0.0.0.0:8080r.Run(":8080")
}
Using BasicAuth() middleware
// simulate some private datavarsecrets= gin.H{
"foo": gin.H{"email": "foo@bar.com", "phone": "123433"},
"austin": gin.H{"email": "austin@example.com", "phone": "666"},
"lena": gin.H{"email": "lena@guapa.com", "phone": "523443"},
}
funcmain() {
r:=gin.Default()
// Group using gin.BasicAuth() middleware// gin.Accounts is a shortcut for map[string]stringauthorized:=r.Group("/admin", gin.BasicAuth(gin.Accounts{
"foo": "bar",
"austin": "1234",
"lena": "hello2",
"manu": "4321",
}))
// /admin/secrets endpoint// hit "localhost:8080/admin/secretsauthorized.GET("/secrets", func(c*gin.Context) {
// get user, it was set by the BasicAuth middlewareuser:=c.MustGet(gin.AuthUserKey).(string)
ifsecret, ok:=secrets[user]; ok {
c.JSON(http.StatusOK, gin.H{"user": user, "secret": secret})
} else {
c.JSON(http.StatusOK, gin.H{"user": user, "secret": "NO SECRET :("})
}
})
// Listen and server on 0.0.0.0:8080r.Run(":8080")
}
Goroutines inside a middleware
When starting inside a middleware or handler, you SHOULD NOT use the original context inside it, you have to use a read-only copy.
funcmain() {
r:=gin.Default()
r.GET("/long_async", func(c*gin.Context) {
// create copy to be used inside the goroutinecCp:=c.Copy()
gofunc() {
// simulate a long task with time.Sleep(). 5 secondstime.Sleep(5*time.Second)
// note that you are using the copied context "cCp", IMPORTANTlog.Println("Done! in path "+cCp.Request.URL.Path)
}()
})
r.GET("/long_sync", func(c*gin.Context) {
// simulate a long task with time.Sleep(). 5 secondstime.Sleep(5*time.Second)
// since we are NOT using a goroutine, we do not have to copy the contextlog.Println("Done! in path "+c.Request.URL.Path)
})
// Listen and server on 0.0.0.0:8080r.Run(":8080")
}
Gin is a HTTP web framework written in Go (Golang). It features a Martini-like API with much better performance -- up to 40 times faster. If you need smashing performance, get yourself some Gin.