Gin Framework Series 02: маршрутизация и параметры

Go

обзор

В предыдущем разделе мы использовали фреймворк Gin для быстрого создания интерфейса GET-запроса, сегодня мы узнаем, как получить маршруты и параметры.

глагол запроса

Знаком сRESTfulстуденты должны знать, чтоRESTfulЭто стиль дизайна и метод разработки сетевых приложений.Каждый URI представляет собой ресурс.POST,DELETE,PUT,GETСуществует четыре метода запросов для добавления, удаления, изменения и запроса ресурсов.

Точно так же, в дополнение к этим четырем глаголам, структура Gin предоставляет намPATCH,OPTION,HEADПодождите, подробности можно посмотретьrentergroup.goдокументIRoutesинтерфейс.

type IRoutes interface {
    Use(...HandlerFunc) IRoutes

    Handle(string, string, ...HandlerFunc) IRoutes
    Any(string, ...HandlerFunc) IRoutes
    GET(string, ...HandlerFunc) IRoutes
    POST(string, ...HandlerFunc) IRoutes
    DELETE(string, ...HandlerFunc) IRoutes
    PATCH(string, ...HandlerFunc) IRoutes
    PUT(string, ...HandlerFunc) IRoutes
    OPTIONS(string, ...HandlerFunc) IRoutes
    HEAD(string, ...HandlerFunc) IRoutes

    StaticFile(string, string) IRoutes
    Static(string, string) IRoutes
    StaticFS(string, http.FileSystem) IRoutes
}

так какRenterGroupДостигнутоIRoutesопределены все глаголы запроса, иgin.DefaultвозвращениеEngineТип наследуетRenterGroup, поэтому его очень просто использовать, просто передайтеgin.DefaultСоздайте экземпляр объекта, и все последующие операции маршрутизации можно будет использовать через этот объект.

file

func main() {
    router := gin.Default()
    router.POST("/article", func(c *gin.Context) {
        c.String(200, "article post")
    })
    router.DELETE("/article", func(c *gin.Context) {
        c.String(200, "article delete")
    })
    router.PUT("/article", func(c *gin.Context) {
        c.String(200, "article put")
    })
    router.GET("/article", func(c *gin.Context) {
        c.String(200, "article get")
    })
    router.Run()
}

Первый параметр команды запроса — это путь запроса, а второй параметр — это функция, используемая для логической обработки, которая может быть анонимной или иметь имя функции, определенное в другом месте. Различные глаголы запроса могут определять один и тот же путь, и нужно только переключить глаголы, чтобы войти в соответствующую логику обработки.

curl -X PUT http://localhost:8080/article
curl -X POST http://localhost:8080/article
curl -X GET http://localhost:8080/article
curl -X DELETE http://localhost:8080/article

параметр маршрута

Существует два типа запросов GET, один из которых добавляется после URL-адреса.?name=pingye, у этого есть имя параметра, а другой должен добавить значение параметра непосредственно к пути/article/1, который не имеет имени параметра и должен быть проанализирован в коде.

protocol://hostname:[port]/path/[query]#fragment

Давайте сначала посмотрим на геймплей маршрутизации, несущей значения параметров, Вот вопрос, как использовать Gin для получения значений параметров по следующей ссылке1.

file

Реализация очень проста, просто нужно установить заполнитель в маршруте:id, двоеточие является знаком заполнителя, имя параметра после двоеточия можно настроить, Джин сопоставит маршрут с адресом запроса, если совпадение прошло успешно, будет1назначить в качестве заполнителя:id, просто позвониc.Paramвы можете получитьidзначение .

router.GET("/article/:id", func(c *gin.Context) {
  id := c.Param("id")
  c.String(200, id)
})

но,:idСуществует проблема с заполнителями, еслиidЕсли значение параметра передано пустым, будет404сообщение об ошибке.

file

Итак, Джин предоставляет еще один заполнитель*id, вы можете использовать его для достижения цели получения нулевого значения.

router.GET("/article/*id", func(c *gin.Context) {
  id := c.Param("id")
  c.String(200, id)
})

Общие параметры

Помимо значений параметров, переносимых маршрутом, рассмотрим более традиционныеGETспособ передачи параметров.

http://localhost:8080/welcome?firstname=Jane&lastname=Doe

в состоянии пройтиc.Queryилиc.DefaultQueryМетод получает параметр после вопросительного знака.

router.GET("/welcome", func(c *gin.Context) {
   firstname := c.DefaultQuery("firstname", "pingyeaa")
   lastname := c.Query("lastname")
   c.String(200, firstname+" "+lastname)
})

Оба они в конечном итоге вызываютGetQueryметод, разница только вDefaultQueryВыполните обработку значений по умолчанию.

func (c *Context) DefaultQuery(key, defaultValue string) string {
    if value, ok := c.GetQuery(key); ok {
        return value
    }
    return defaultValue
}

func (c *Context) Query(key string) string {
    value, _ := c.GetQuery(key)
    return value
}

параметр формы

Форма отправлена ​​из HTMLformКонтент также легко доступен.

router.POST("/form_post", func(c *gin.Context) {
  message := c.PostForm("message")
  nick := c.DefaultPostForm("nick", "anonymous")

  c.JSON(200, gin.H{
    "status":  "posted",
    "message": message,
    "nick":    nick,
  })
})
curl -d "message=pingye" http://localhost:8080/form_post
{"message":"pingye","nick":"anonymous","status":"posted"}

параметр типа массива

Иногда (например, флажки) интерфейсная страница будет передавать значение типа массива, этот типnameТо же самое, но хранимый контент другой.

POST /post?ids[a]=1234&ids[b]=hello HTTP/1.1
Content-Type: application/x-www-form-urlencoded

все ещеQueryMapМетод выполнен, метод возвращается по умолчаниюmapтип.

router.GET("/post", func(c *gin.Context) {
  ids := c.QueryMap("ids")
  c.String(200, ids["a"]+" "+ids["b"])
})
curl http://localhost:8080/post?ids[a]=pingye&ids[b]=hehe
pingye hehe

Файл загружен

При нормальных обстоятельствах загрузка файла будет напрямую передаваться из внешнего интерфейса поставщикам услуг облачного хранения, таким как Alibaba Cloud, Qiniu Cloud и т. д., и относительно небольшое количество сценариев будет передаваться на их собственные серверы. чтобы избежать书到用时方恨少бывает, давайте разбираться.

Джин обеспечиваетFormFileметод для получения файлового потока, этот метод возвращаетFileHeaderПеременная типа, которую можно вызватьFilenameсвойства, чтобы увидеть имя файла.

type FileHeader struct {
   Filename string
   Header   textproto.MIMEHeader
   Size     int64

   content []byte
   tmpfile string
}
router.POST("/upload", func(c *gin.Context) {
  file, _ := c.FormFile("file")
  c.String(200, file.Filename)
})

пройти черезcurlЗапросив интерфейс, вы можете видеть, что легко получить имя файла.

curl -X POST http://localhost:8080/upload \
  -F "file=@/Users/enoch/Downloads/IMG_9216.JPG" \
  -H "Content-Type: multipart/form-data"
IMG_9216.JPG

Конечно, мы можем не только получить имя файла, но и использоватьSaveUploadedFileМетод сохраняет файл в определенное место.При сохранении файла убедитесь, что у вас есть разрешение на операцию целевого каталога.

router.POST("/upload", func(c *gin.Context) {
        file, _ := c.FormFile("file")
        c.String(200, file.Filename)
        err := c.SaveUploadedFile(file, "/Users/enoch/Desktop/ab.png")
        if err != nil {
            c.String(500, err.Error())
        }
})

пакеты маршрутизации

При значительных изменениях в интерфейсе (таких как параметры ввода и вывода) с учетом обратной совместимости обычно добавляется интерфейс, но есть надежда, что имя нового интерфейса, очевидно, является обновленной версией старого интерфейса. Префикс имени с номером версииv1/articleэта форма.

v1 := r.Group("v1")
{
  v1.POST("/login", func(c *gin.Context) {
    c.String(200, "v1/login")
  })
  v1.POST("/submit", func(c *gin.Context) {
    c.String(200, "v1/submit")
  })
}

v2 := r.Group("v2")
{
  v2.POST("/login", func(c *gin.Context) {
    c.String(200, "v2/login")
  })
  v2.POST("/submit", func(c *gin.Context) {
    c.String(200, "v2/submit")
  })
}
curl -X POST http://localhost:8080/v1/login
curl -X POST http://localhost:8080/v2/login

Пример кода языковой библиотеки Go, приветственная звездочкаGitHub.com/Hiranoahah/go…


Спасибо за просмотр.Если вы считаете, что статья была вам полезна, обратите внимание на паблик-аккаунт "Pingye", посвященный языку Go и техническим принципам.关注我