参数获取

源码路径:github.com/gin-gonic/gin/context.go

URL

  1. func (c *Context) Param(key string) string

eg:

  1. router.GET("/user/:id", func(c *gin.Context) {
  2. // // a GET request to /user/john
  3. id := c.Param("id") // id == "john"
  4. })

query

  1. // It is shortcut for `c.Request.URL.Query().Get(key)`
  2. // GET /path?id=1234&name=Manu&value=
  3. // c.Query("id") == "1234"
  4. // c.Query("name") == "Manu"
  5. // c.Query("value") == ""
  6. // c.Query("wtf") == ""
  7. func (c *Context) Query(key string) string {
  8. value, _ := c.GetQuery(key)
  9. return value
  10. }

其他方式query

  1. func (c *Context) QueryArray(key string) []string {
  2. values, _ := c.GetQueryArray(key)
  3. return values
  4. }
  5. func (c *Context) getQueryCache() {
  6. if c.queryCache == nil {
  7. c.queryCache = c.Request.URL.Query()
  8. }
  9. }
  10. // GetQueryArray returns a slice of strings for a given query key, plus
  11. // a boolean value whether at least one value exists for the given key.
  12. func (c *Context) GetQueryArray(key string) ([]string, bool) {
  13. c.getQueryCache()
  14. if values, ok := c.queryCache[key]; ok && len(values) > 0 {
  15. return values, true
  16. }
  17. return []string{}, false
  18. }
  19. // QueryMap returns a map for a given query key.
  20. func (c *Context) QueryMap(key string) map[string]string {
  21. dicts, _ := c.GetQueryMap(key)
  22. return dicts
  23. }
  24. // GetQueryMap returns a map for a given query key, plus a boolean value
  25. // whether at least one value exists for the given key.
  26. func (c *Context) GetQueryMap(key string) (map[string]string, bool) {
  27. c.getQueryCache()
  28. return c.get(c.queryCache, key)
  29. }

PostForm

  1. // PostForm returns the specified key from a POST urlencoded form or multipart form
  2. // when it exists, otherwise it returns an empty string `("")`.
  3. func (c *Context) PostForm(key string) string {
  4. value, _ := c.GetPostForm(key)
  5. return value
  6. }
  7. // DefaultPostForm returns the specified key from a POST urlencoded form or multipart form
  8. // when it exists, otherwise it returns the specified defaultValue string.
  9. // See: PostForm() and GetPostForm() for further information.
  10. func (c *Context) DefaultPostForm(key, defaultValue string) string {
  11. if value, ok := c.GetPostForm(key); ok {
  12. return value
  13. }
  14. return defaultValue
  15. }
  16. // GetPostForm is like PostForm(key). It returns the specified key from a POST urlencoded
  17. // form or multipart form when it exists `(value, true)` (even when the value is an empty string),
  18. // otherwise it returns ("", false).
  19. // For example, during a PATCH request to update the user's email:
  20. // email=mail@example.com --> ("mail@example.com", true) := GetPostForm("email") // set email to "mail@example.com"
  21. // email= --> ("", true) := GetPostForm("email") // set email to ""
  22. // --> ("", false) := GetPostForm("email") // do nothing with email
  23. func (c *Context) GetPostForm(key string) (string, bool) {
  24. if values, ok := c.GetPostFormArray(key); ok {
  25. return values[0], ok
  26. }
  27. return "", false
  28. }
  29. // PostFormArray returns a slice of strings for a given form key.
  30. // The length of the slice depends on the number of params with the given key.
  31. func (c *Context) PostFormArray(key string) []string {
  32. values, _ := c.GetPostFormArray(key)
  33. return values
  34. }
  35. func (c *Context) getFormCache() {
  36. if c.formCache == nil {
  37. c.formCache = make(url.Values)
  38. req := c.Request
  39. if err := req.ParseMultipartForm(c.engine.MaxMultipartMemory); err != nil {
  40. if err != http.ErrNotMultipart {
  41. debugPrint("error on parse multipart form array: %v", err)
  42. }
  43. }
  44. c.formCache = req.PostForm
  45. }
  46. }
  47. // GetPostFormArray returns a slice of strings for a given form key, plus
  48. // a boolean value whether at least one value exists for the given key.
  49. func (c *Context) GetPostFormArray(key string) ([]string, bool) {
  50. c.getFormCache()
  51. if values := c.formCache[key]; len(values) > 0 {
  52. return values, true
  53. }
  54. return []string{}, false
  55. }
  56. // PostFormMap returns a map for a given form key.
  57. func (c *Context) PostFormMap(key string) map[string]string {
  58. dicts, _ := c.GetPostFormMap(key)
  59. return dicts
  60. }
  61. // GetPostFormMap returns a map for a given form key, plus a boolean value
  62. // whether at least one value exists for the given key.
  63. func (c *Context) GetPostFormMap(key string) (map[string]string, bool) {
  64. c.getFormCache()
  65. return c.get(c.formCache, key)
  66. }
  67. // get is an internal method and returns a map which satisfy conditions.
  68. func (c *Context) get(m map[string][]string, key string) (map[string]string, bool) {
  69. dicts := make(map[string]string)
  70. exist := false
  71. for k, v := range m {
  72. if i := strings.IndexByte(k, '['); i >= 1 && k[0:i] == key {
  73. if j := strings.IndexByte(k[i+1:], ']'); j >= 1 {
  74. exist = true
  75. dicts[k[i+1:][:j]] = v[0]
  76. }
  77. }
  78. }
  79. return dicts, exist
  80. }

上传

  1. // FormFile returns the first file for the provided form key.
  2. func (c *Context) FormFile(name string) (*multipart.FileHeader, error) {
  3. if c.Request.MultipartForm == nil {
  4. if err := c.Request.ParseMultipartForm(c.engine.MaxMultipartMemory); err != nil {
  5. return nil, err
  6. }
  7. }
  8. f, fh, err := c.Request.FormFile(name)
  9. if err != nil {
  10. return nil, err
  11. }
  12. f.Close()
  13. return fh, err
  14. }
  15. // MultipartForm is the parsed multipart form, including file uploads.
  16. func (c *Context) MultipartForm() (*multipart.Form, error) {
  17. err := c.Request.ParseMultipartForm(c.engine.MaxMultipartMemory)
  18. return c.Request.MultipartForm, err
  19. }
  20. // SaveUploadedFile uploads the form file to specific dst.
  21. func (c *Context) SaveUploadedFile(file *multipart.FileHeader, dst string) error {
  22. src, err := file.Open()
  23. if err != nil {
  24. return err
  25. }
  26. defer src.Close()
  27. out, err := os.Create(dst)
  28. if err != nil {
  29. return err
  30. }
  31. defer out.Close()
  32. _, err = io.Copy(out, src)
  33. return err
  34. }

参数校验/binding

源码地址github.com/gin-gonic/gin/binding/binding.go
提供的默认的类型

  1. var (
  2. JSON = jsonBinding{}
  3. XML = xmlBinding{}
  4. Form = formBinding{}
  5. Query = queryBinding{}
  6. FormPost = formPostBinding{}
  7. FormMultipart = formMultipartBinding{}
  8. ProtoBuf = protobufBinding{}
  9. MsgPack = msgpackBinding{}
  10. YAML = yamlBinding{}
  11. Uri = uriBinding{}
  12. Header = headerBinding{}
  13. )

定义需要实现的接口

  1. type Binding interface {
  2. Name() string
  3. Bind(*http.Request, interface{}) error
  4. }
  5. // BindingBody adds BindBody method to Binding. BindBody is similar with Bind,
  6. // but it reads the body from supplied bytes instead of req.Body.
  7. type BindingBody interface {
  8. Binding
  9. BindBody([]byte, interface{}) error
  10. }

例如json的实现类

  1. type jsonBinding struct{}
  2. func (jsonBinding) Name() string {
  3. return "json"
  4. }
  5. func (jsonBinding) Bind(req *http.Request, obj interface{}) error {
  6. if req == nil || req.Body == nil {
  7. return fmt.Errorf("invalid request")
  8. }
  9. return decodeJSON(req.Body, obj)
  10. }
  11. func (jsonBinding) BindBody(body []byte, obj interface{}) error {
  12. return decodeJSON(bytes.NewReader(body), obj)
  13. }
  14. func decodeJSON(r io.Reader, obj interface{}) error {
  15. decoder := json.NewDecoder(r)
  16. if EnableDecoderUseNumber {
  17. decoder.UseNumber()
  18. }
  19. if EnableDecoderDisallowUnknownFields {
  20. decoder.DisallowUnknownFields()
  21. }
  22. if err := decoder.Decode(obj); err != nil {
  23. return err
  24. }
  25. return validate(obj)
  26. }

校验

  1. / Bind checks the Content-Type to select a binding engine automatically,
  2. // Depending the "Content-Type" header different bindings are used:
  3. // "application/json" --> JSON binding
  4. // "application/xml" --> XML binding
  5. // otherwise --> returns an error.
  6. // It parses the request's body as JSON if Content-Type == "application/json" using JSON or XML as a JSON input.
  7. // It decodes the json payload into the struct specified as a pointer.
  8. // It writes a 400 error and sets Content-Type header "text/plain" in the response if input is not valid.
  9. func (c *Context) Bind(obj interface{}) error {
  10. b := binding.Default(c.Request.Method, c.ContentType())
  11. return c.MustBindWith(obj, b)
  12. }
  13. // BindJSON is a shortcut for c.MustBindWith(obj, binding.JSON).
  14. func (c *Context) BindJSON(obj interface{}) error {
  15. return c.MustBindWith(obj, binding.JSON)
  16. }
  17. // MustBindWith binds the passed struct pointer using the specified binding engine.
  18. // It will abort the request with HTTP 400 if any error occurs.
  19. // See the binding package.
  20. func (c *Context) MustBindWith(obj interface{}, b binding.Binding) error {
  21. if err := c.ShouldBindWith(obj, b); err != nil {
  22. c.AbortWithError(http.StatusBadRequest, err).SetType(ErrorTypeBind) // nolint: errcheck
  23. return err
  24. }
  25. return nil
  26. }
  27. // ShouldBindWith binds the passed struct pointer using the specified binding engine.
  28. // See the binding package.
  29. func (c *Context) ShouldBindWith(obj interface{}, b binding.Binding) error {
  30. return b.Bind(c.Request, obj)
  31. }