|
|
@@ -40,7 +40,7 @@ $ go run example.go
|
|
|
|
|
|
## Benchmarks
|
|
|
|
|
|
-Gin uses a custom version of [HttpRouter](https://github.com/julienschmidt/httprouter)
|
|
|
+Gin uses a custom version of [HttpRouter](https://github.com/julienschmidt/httprouter)
|
|
|
|
|
|
[See all benchmarks](/BENCHMARKS.md)
|
|
|
|
|
|
@@ -74,10 +74,10 @@ BenchmarkTigerTonic_GithubAll | 1000 | 1439483 | 239104
|
|
|
BenchmarkTraffic_GithubAll | 100 | 11383067 | 2659329 | 21848
|
|
|
BenchmarkVulcan_GithubAll | 5000 | 394253 | 19894 | 609
|
|
|
|
|
|
-(1): Total Repetitions achieved in constant time, higher means more confident result
|
|
|
-(2): Single Repetition Duration (ns/op), lower is better
|
|
|
-(3): Heap Memory (B/op), lower is better
|
|
|
-(4): Average Allocations per Repetition (allocs/op), lower is better
|
|
|
+(1): Total Repetitions achieved in constant time, higher means more confident result
|
|
|
+(2): Single Repetition Duration (ns/op), lower is better
|
|
|
+(3): Heap Memory (B/op), lower is better
|
|
|
+(4): Average Allocations per Repetition (allocs/op), lower is better
|
|
|
|
|
|
## Gin v1. stable
|
|
|
|
|
|
@@ -281,10 +281,10 @@ func main() {
|
|
|
// single file
|
|
|
file, _ := c.FormFile("file")
|
|
|
log.Println(file.Filename)
|
|
|
-
|
|
|
+
|
|
|
// Upload the file to specific dst.
|
|
|
- // c.SaveUploadedFile(file, dst)
|
|
|
-
|
|
|
+ // c.SaveUploadedFile(file, dst)
|
|
|
+
|
|
|
c.String(http.StatusOK, fmt.Sprintf("'%s' uploaded!", file.Filename))
|
|
|
})
|
|
|
router.Run(":8080")
|
|
|
@@ -313,9 +313,9 @@ func main() {
|
|
|
|
|
|
for _, file := range files {
|
|
|
log.Println(file.Filename)
|
|
|
-
|
|
|
+
|
|
|
// Upload the file to specific dst.
|
|
|
- // c.SaveUploadedFile(file, dst)
|
|
|
+ // c.SaveUploadedFile(file, dst)
|
|
|
}
|
|
|
c.String(http.StatusOK, fmt.Sprintf("%d files uploaded!", len(files)))
|
|
|
})
|
|
|
@@ -487,6 +487,67 @@ func main() {
|
|
|
}
|
|
|
```
|
|
|
|
|
|
+### Custom Validators
|
|
|
+
|
|
|
+It is also possible to register custom validators. See the [example code](examples/custom-validation/server.go).
|
|
|
+
|
|
|
+[embedmd]:# (examples/custom-validation/server.go go)
|
|
|
+```go
|
|
|
+package main
|
|
|
+
|
|
|
+import (
|
|
|
+ "net/http"
|
|
|
+ "reflect"
|
|
|
+ "time"
|
|
|
+
|
|
|
+ "github.com/gin-gonic/gin"
|
|
|
+ "github.com/gin-gonic/gin/binding"
|
|
|
+ validator "gopkg.in/go-playground/validator.v8"
|
|
|
+)
|
|
|
+
|
|
|
+type Booking struct {
|
|
|
+ CheckIn time.Time `form:"check_in" binding:"required,bookabledate" time_format:"2006-01-02"`
|
|
|
+ CheckOut time.Time `form:"check_out" binding:"required,gtfield=CheckIn" time_format:"2006-01-02"`
|
|
|
+}
|
|
|
+
|
|
|
+func bookableDate(
|
|
|
+ v *validator.Validate, topStruct reflect.Value, currentStructOrField reflect.Value,
|
|
|
+ field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string,
|
|
|
+) bool {
|
|
|
+ if date, ok := field.Interface().(time.Time); ok {
|
|
|
+ today := time.Now()
|
|
|
+ if today.Year() > date.Year() || today.YearDay() > date.YearDay() {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true
|
|
|
+}
|
|
|
+
|
|
|
+func main() {
|
|
|
+ route := gin.Default()
|
|
|
+ binding.Validator.RegisterValidation("bookabledate", bookableDate)
|
|
|
+ route.GET("/bookable", getBookable)
|
|
|
+ route.Run(":8085")
|
|
|
+}
|
|
|
+
|
|
|
+func getBookable(c *gin.Context) {
|
|
|
+ var b Booking
|
|
|
+ if err := c.ShouldBindWith(&b, binding.Query); err == nil {
|
|
|
+ c.JSON(http.StatusOK, gin.H{"message": "Booking dates are valid!"})
|
|
|
+ } else {
|
|
|
+ c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+```console
|
|
|
+$ curl "localhost:8085/bookable?check_in=2017-08-16&check_out=2017-08-17"
|
|
|
+{"message":"Booking dates are valid!"}
|
|
|
+
|
|
|
+$ curl "localhost:8085/bookable?check_in=2017-08-15&check_out=2017-08-16"
|
|
|
+{"error":"Key: 'Booking.CheckIn' Error:Field validation for 'CheckIn' failed on the 'bookabledate' tag"}
|
|
|
+```
|
|
|
+
|
|
|
### Only Bind Query String
|
|
|
|
|
|
`BindQuery` function only binds the query params and not the post data. See the [detail information](https://github.com/gin-gonic/gin/issues/742#issuecomment-315953017).
|
|
|
@@ -711,7 +772,7 @@ func main() {
|
|
|
// Listen and serve on 0.0.0.0:8080
|
|
|
r.Run(":8080")
|
|
|
}
|
|
|
-```
|
|
|
+```
|
|
|
|
|
|
### Serving static files
|
|
|
|
|
|
@@ -822,7 +883,7 @@ You may use custom delims
|
|
|
r := gin.Default()
|
|
|
r.Delims("{[{", "}]}")
|
|
|
r.LoadHTMLGlob("/path/to/templates"))
|
|
|
-```
|
|
|
+```
|
|
|
|
|
|
#### Custom Template Funcs
|
|
|
|