2015-05-19 02:19:00 +03:00
#Gin Web Framework [![Build Status](https://travis-ci.org/gin-gonic/gin.svg)](https://travis-ci.org/gin-gonic/gin) [![Coverage Status](https://coveralls.io/repos/gin-gonic/gin/badge.svg?branch=develop)](https://coveralls.io/r/gin-gonic/gin?branch=develop)
2014-07-02 16:36:23 +04:00
2015-05-19 02:19:00 +03:00
[![GoDoc ](https://godoc.org/github.com/gin-gonic/gin?status.svg )](https://godoc.org/github.com/gin-gonic/gin) [![Join the chat at https://gitter.im/gin-gonic/gin ](https://badges.gitter.im/Join%20Chat.svg )](https://gitter.im/gin-gonic/gin?utm_source=badge& utm_medium=badge& utm_campaign=pr-badge& utm_content=badge)
2015-02-21 14:24:57 +03:00
2014-11-02 14:23:31 +03:00
Gin is a web framework written in Golang. It features a martini-like API with much better performance, up to 40 times faster thanks to [httprouter ](https://github.com/julienschmidt/httprouter ). If you need performance and good productivity, you will love Gin.
2014-09-13 22:37:27 +04:00
2015-02-04 15:18:37 +03:00
![Gin console logger ](https://gin-gonic.github.io/gin/other/console.png )
2014-07-02 22:52:47 +04:00
2014-09-13 22:37:27 +04:00
```
$ cat test.go
```
```go
package main
2015-03-05 09:14:01 +03:00
import (
"net/http"
"github.com/gin-gonic/gin"
)
2014-09-13 22:37:27 +04:00
func main() {
router := gin.Default()
router.GET("/", func(c *gin.Context) {
2015-03-05 09:14:01 +03:00
c.String(http.StatusOK, "hello world")
2014-09-13 22:37:27 +04:00
})
router.GET("/ping", func(c *gin.Context) {
2015-03-05 09:14:01 +03:00
c.String(http.StatusOK, "pong")
2014-09-13 22:37:27 +04:00
})
router.POST("/submit", func(c *gin.Context) {
2015-03-05 09:14:01 +03:00
c.String(http.StatusUnauthorized, "not authorized")
2014-09-13 22:37:27 +04:00
})
router.PUT("/error", func(c *gin.Context) {
2015-04-30 15:32:50 +03:00
c.String(http.StatusInternalServerError, "an error happened :(")
2014-09-13 22:37:27 +04:00
})
router.Run(":8080")
}
```
2014-07-02 22:52:47 +04:00
##Gin is new, will it be supported?
2015-02-05 01:00:51 +03:00
Yes, Gin is an internal tool of [Manu ](https://github.com/manucorporat ) and [Javi ](https://github.com/javierprovecho ) for many of our projects/start-ups. We developed it and we are going to continue using and improve it.
2014-07-02 22:52:47 +04:00
2014-07-18 17:22:38 +04:00
##Roadmap for v1.0
2014-07-05 21:27:33 +04:00
- [ ] Ask our designer for a cool logo
2014-07-06 20:57:58 +04:00
- [ ] Add tons of unit tests
- [ ] Add internal benchmarks suite
2015-02-05 01:00:51 +03:00
- [ ] More powerful validation API
- [ ] Improve documentation
- [ ] Add Swagger support
- [x] Stable API
2014-07-05 21:27:33 +04:00
- [x] Improve logging system
- [x] Improve JSON/XML validation using bindings
2014-07-06 20:57:58 +04:00
- [x] Improve XML support
2014-07-18 17:22:38 +04:00
- [x] Flexible rendering system
2015-02-05 01:00:51 +03:00
- [x] Add more cool middlewares, for example redis caching (this also helps developers to understand the framework).
2014-07-05 21:28:45 +04:00
- [x] Continuous integration
2015-02-05 01:00:51 +03:00
- [x] Performance improments, reduce allocation and garbage collection overhead
- [x] Fix bugs
2014-07-02 22:52:47 +04:00
2014-06-18 03:42:34 +04:00
## Start using it
2014-09-03 19:42:49 +04:00
Obviously, you need to have Git and Go already installed to run Gin.
2014-07-04 06:30:30 +04:00
Run this in your terminal
2014-06-18 03:42:34 +04:00
```
go get github.com/gin-gonic/gin
```
2014-09-03 19:42:49 +04:00
Then import it in your Go code:
2014-06-18 03:42:34 +04:00
```
import "github.com/gin-gonic/gin"
```
##API Examples
#### Create most basic PING/PONG HTTP endpoint
2014-06-30 05:58:10 +04:00
```go
2014-07-04 21:44:07 +04:00
package main
2015-03-05 09:14:01 +03:00
import (
"net/http"
"github.com/gin-gonic/gin"
)
2014-06-30 05:58:10 +04:00
2014-06-18 03:42:34 +04:00
func main() {
2014-07-04 21:44:07 +04:00
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
2015-03-05 09:14:01 +03:00
c.String(http.StatusOK, "pong")
2014-07-04 21:44:07 +04:00
})
2015-02-08 23:43:41 +03:00
// Listen and serve on 0.0.0.0:8080
2014-07-04 21:44:07 +04:00
r.Run(":8080")
2014-06-30 05:58:10 +04:00
}
```
2014-07-03 18:16:40 +04:00
#### Using GET, POST, PUT, PATCH, DELETE and OPTIONS
2014-06-30 05:58:10 +04:00
```go
func main() {
2014-07-04 21:44:07 +04:00
// Creates a gin router + logger and recovery (crash-free) middlewares
r := gin.Default()
2014-06-18 03:42:34 +04:00
2014-07-04 21:44:07 +04:00
r.GET("/someGet", getting)
r.POST("/somePost", posting)
r.PUT("/somePut", putting)
r.DELETE("/someDelete", deleting)
r.PATCH("/somePatch", patching)
2014-07-04 23:37:33 +04:00
r.HEAD("/someHead", head)
r.OPTIONS("/someOptions", options)
2014-07-04 21:44:07 +04:00
// Listen and server on 0.0.0.0:8080
r.Run(":8080")
2014-06-18 03:42:34 +04:00
}
```
#### Parameters in path
2014-06-30 05:58:10 +04:00
```go
2014-06-18 03:42:34 +04:00
func main() {
2014-07-04 21:44:07 +04:00
r := gin.Default()
2014-07-08 13:55:20 +04:00
// This handler will match /user/john but will not match neither /user/ or /user
2014-07-04 21:44:07 +04:00
r.GET("/user/:name", func(c *gin.Context) {
name := c.Params.ByName("name")
2014-07-04 23:37:33 +04:00
message := "Hello "+name
2015-03-05 09:14:01 +03:00
c.String(http.StatusOK, message)
2014-07-04 23:37:33 +04:00
})
2015-01-31 15:09:44 +03:00
// However, this one will match /user/john/ and also /user/john/send
// If no other routers match /user/john, it will redirect to /user/join/
2014-07-08 13:55:20 +04:00
r.GET("/user/:name/*action", func(c *gin.Context) {
2014-07-04 23:37:33 +04:00
name := c.Params.ByName("name")
action := c.Params.ByName("action")
message := name + " is " + action
2015-03-05 09:14:01 +03:00
c.String(http.StatusOK, message)
2014-07-04 21:44:07 +04:00
})
2014-07-08 13:55:20 +04:00
2014-07-04 21:44:07 +04:00
// Listen and server on 0.0.0.0:8080
r.Run(":8080")
2014-06-18 03:42:34 +04:00
}
```
2015-02-06 20:14:12 +03:00
###Form parameters
```go
func main() {
r := gin.Default()
// This will respond to urls like search?firstname=Jane& lastname=Doe
r.GET("/search", func(c *gin.Context) {
// You need to call ParseForm() on the request to receive url and form params first
c.Request.ParseForm()
firstname := c.Request.Form.Get("firstname")
2015-02-08 07:07:06 +03:00
lastname := c.Request.Form.Get("lastname")
2015-02-06 20:14:12 +03:00
message := "Hello "+ firstname + lastname
2015-03-05 09:14:01 +03:00
c.String(http.StatusOK, message)
2015-02-06 20:14:12 +03:00
})
r.Run(":8080")
}
```
2014-06-18 03:42:34 +04:00
2015-03-08 17:50:23 +03:00
###Multipart Form
```go
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) {
var form LoginForm
c.BindWith(& form, binding.MultipartForm)
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(":8080")
}
```
Test it with:
```bash
$ curl -v --form user=user --form password=password http://localhost:8080/login
```
2014-06-18 03:42:34 +04:00
#### Grouping routes
2014-06-30 05:58:10 +04:00
```go
2014-06-18 03:42:34 +04:00
func main() {
2014-07-04 21:44:07 +04:00
r := gin.Default()
2014-06-18 03:42:34 +04:00
2014-07-04 21:44:07 +04:00
// Simple group: v1
v1 := r.Group("/v1")
{
v1.POST("/login", loginEndpoint)
v1.POST("/submit", submitEndpoint)
v1.POST("/read", readEndpoint)
}
// Simple group: v2
v2 := r.Group("/v2")
{
v2.POST("/login", loginEndpoint)
v2.POST("/submit", submitEndpoint)
v2.POST("/read", readEndpoint)
}
// Listen and server on 0.0.0.0:8080
r.Run(":8080")
2014-06-18 03:42:34 +04:00
}
```
#### Blank Gin without middlewares by default
Use
2014-06-30 05:58:10 +04:00
```go
2014-06-18 03:42:34 +04:00
r := gin.New()
```
instead of
2014-06-30 05:58:10 +04:00
```go
2014-06-18 03:42:34 +04:00
r := gin.Default()
```
#### Using middlewares
2014-06-30 05:58:10 +04:00
```go
2014-06-18 03:42:34 +04:00
func main() {
2014-07-04 21:44:07 +04:00
// Creates a router without any middleware by default
r := gin.New()
// Global middlewares
r.Use(gin.Logger())
r.Use(gin.Recovery())
// Per route middlewares, you can add as many as you desire.
r.GET("/benchmark", MyBenchLogger(), benchEndpoint)
// Authorization group
// authorized := r.Group("/", AuthRequired())
// exactly the same than:
authorized := r.Group("/")
// per group middlewares! 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 group
testing := authorized.Group("testing")
testing.GET("/analytics", analyticsEndpoint)
}
// Listen and server on 0.0.0.0:8080
r.Run(":8080")
2014-06-18 03:42:34 +04:00
}
```
2014-08-03 03:31:48 +04:00
#### Model binding and validation
2014-06-18 03:42:34 +04:00
2014-08-03 03:31:48 +04:00
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.