英文:
How to extract comma separated values from query parameter in Go?
问题
我正在使用Gin Web Framework,并尝试找到一种将逗号分隔的值列表从查询参数绑定到结构体的方法。以下是我的代码片段:
type QueryParams struct {
Type []string `form:"type"`
}
func BulkRead(c *gin.Context) {
params := QueryParams{
Type: []string{},
}
if err := c.ShouldBindQuery(¶ms); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "无法绑定查询参数"})
return
}
c.Status(200)
}
请求:GET /api/v1/car?type=ford,audi
我期望的结果:["ford", "audi"]
我得到的结果:"ford,audi"
有没有简单的方法可以实现这个?还是我需要编写一个自定义函数来处理这个?
英文:
I am using the Gin Web Framework and I am trying to find a way to bind a list of comma separated values from a query parameter into a struct. The following is a snippet of my code:
type QueryParams struct {
Type []string `form:"type"`
}
func BulkRead(c *gin.Context) {
params := QueryParams{
Type: []string{},
}
if err := c.ShouldBindQuery(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "couldn't bind query params"})
return
}
c.Status(200)
}
Request: GET /api/v1/car?type=ford,audi
What I expect: ["ford", "audi"]
What I am getting: "ford,audi"
Is there an easy way to do this? Or will I need to write a custom function to handle this?
答案1
得分: 3
要从查询参数中提取逗号分隔的值,你可以使用strings
包中的Split()
方法。我为你的情况创建了一个简单的程序,如下所示:
package main
import (
"fmt"
"strconv"
"strings"
)
func main() {
var cars []string
qryResult := "ford,audi"
carBrands := strings.Split(qryResult, ",")
fmt.Println(carBrands)
for i := 0; i < len(carBrands); i++ {
cars = append(cars, strconv.Quote(carBrands[i]))
}
fmt.Println(cars)
}
输出结果:
[ford audi]
["ford" "audi"]
这段代码可以从查询参数中提取逗号分隔的值,并将其存储在一个字符串切片中。然后,它使用strconv.Quote()
方法将每个值添加到另一个字符串切片中,并打印出结果。
英文:
To extract comma separated values from query parameter you can make use of Split()
method from strings
package .I have created a simple program for your scenario as follows :
package main
import (
"fmt"
"strconv"
"strings"
)
func main() {
var cars []string
qryResult := "ford,audi"
carBrands := strings.Split(qryResult, ",")
fmt.Println(carBrands)
for i := 0; i < len(carBrands); i++ {
cars = append(cars, strconv.Quote(carBrands[i]))
}
fmt.Println(cars)
}
Output:
[ford audi]
["ford" "audi"]
答案2
得分: 1
可能没有这样的方法。
通常我会这样做:
type QueryParams struct {
Type string `form:"type"`
}
func (q *QueryParams) Types() []string {
return strings.Split(q.Type, ",")
}
func BulkRead(c *gin.Context) {
params := new(QueryParams)
if err := c.ShouldBindQuery(¶ms); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "无法绑定查询参数"})
return
}
c.JSONP(200, map[string]interface{}{
"types": params.Types(),
})
}
英文:
There may not be such a way.
Usually I do this:
type QueryParams struct {
Type string `form:"type"`
}
func (q *QueryParams) Types() []string {
return strings.Split(q.Type, ",")
}
func BulkRead(c *gin.Context) {
params := new(QueryParams)
if err := c.ShouldBindQuery(&params); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "couldn't bind query params"})
return
}
c.JSONP(200, map[string]interface{}{
"types": params.Types(),
})
}
</details>
# 答案3
**得分**: 0
Gin没有提供直接的方法来完成这个任务。最简单的解决方案是自己获取查询参数并进行拆分。以下是只需两行代码的示例:
```go
func MyHandler(c *gin.Context) {
ss := strings.Split(c.Query("type"), ",")
fmt.Println(ss) // [ford audi]
qp := QueryParams{
Type: ss,
}
}
如果你可以更改请求的方式,可以将其改为:
GET /api/v1/car?type=ford&type=audi
(重复查询键)
或者对逗号进行URL编码:
GET /api/v1/car?type=ford%20audi
(,
-> %20
)
然后,context.GetQueryArray
将按预期工作:
func MyHandler(c *gin.Context) {
cars, _ := c.GetQueryArray("type")
fmt.Println(cars) // [ford audi]
}
当然,你也可以实现自己的 binding.Binding
,适用于有多个查询参数并希望将绑定逻辑封装到一个地方的情况,但我觉得对于你的用例来说有点过度设计:
type commaSepQueryBinding struct {}
func (commaSepQueryBinding) Name() string {
return "comma-sep-query"
}
func (commaSepQueryBinding) Bind(req *http.Request, obj interface{}) error {
values := req.URL.Query()
p := obj.(*QueryParams)
p.Type = strings.Split(values["type"][0], ",")
return nil
}
func MyHandler(c *gin.Context) {
q := QueryParams{}
err := c.ShouldBindWith(&q, &commaSepQueryBinding{})
if err != nil {
panic(err)
}
fmt.Println(q.Type) // [ford audi]
}
英文:
Gin doesn't have a way to do this for you. The easiest solution is to just get the query param and split it yourself. This is literally 2 lines of code:
func MyHandler(c *gin.Context) {
ss := strings.Split(c.Query("type"), ",")
fmt.Println(ss) // [ford audi]
qp := QueryParams{
Type: ss,
}
}
<hr>
If you have the option to change how the request is made, change it to:
GET /api/v1/car?type=ford&type=audi
(repeat the query key)
or URL-encode the comma:
GET /api/v1/car?type=ford%20audi
(,
-> %20
)
Then context.GetQueryArray
will work as you expect:
func MyHandler(c *gin.Context) {
cars, _ := c.GetQueryArray("type")
fmt.Println(cars) // [ford audi]
}
<hr>
Of course implementing your own binding.Binding
is an option, suited if you have more than just that query parameter and want to encapsulate the binding logic into one place, but I feel it's overkill for your use case:
type commaSepQueryBinding struct {}
func (commaSepQueryBinding) Name() string {
return "comma-sep-query"
}
func (commaSepQueryBinding) Bind(req *http.Request, obj interface{}) error {
values := req.URL.Query()
p := obj.(*QueryParams)
p.Type = strings.Split(values["type"][0], ",")
return nil
}
func MyHandler(c *gin.Context) {
q := QueryParams{}
err := c.ShouldBindWith(&q, &commaSepQueryBinding{})
if err != nil {
panic(err)
}
fmt.Println(q.Type) // [ford audi]
}
答案4
得分: -1
这是一个Go语言的代码示例,使用了Gin框架来创建一个HTTP服务器。以下是代码的翻译:
package main
import (
"log"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
type TypeBinding struct {
name string
}
func NewTypeBinding(name string) *TypeBinding {
return &TypeBinding{
name: name,
}
}
func (t *TypeBinding) Name() string {
return t.name
}
func (t *TypeBinding) Bind(r *http.Request, i interface{}) error {
ttype := r.URL.Query().Get(t.name)
ii := i.(*QueryParams)
ii.Type = strings.Split(ttype, ",")
return nil
}
type QueryParams struct {
Type []string `url:"type"`
}
func ggin() {
router := gin.Default()
typeBinding := NewTypeBinding("type")
var opt QueryParams
router.GET("/", func(c *gin.Context) {
if err := c.MustBindWith(&opt, typeBinding); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "无法绑定查询参数"})
return
}
log.Printf("type: %v", opt.Type)
c.String(http.StatusOK, "type: %s", opt.Type)
})
router.Run(":8080")
}
这段代码创建了一个HTTP服务器,监听在8080端口。当访问根路径"/"时,服务器会尝试将查询参数绑定到QueryParams
结构体的Type
字段上,并将绑定结果打印出来。如果绑定失败,服务器会返回一个错误响应。
英文:
It might be helpful for you too.
package main
import (
"log"
"net/http"
"strings"
"github.com/gin-gonic/gin"
)
type TypeBinding struct {
name string
}
func NewTypeBinding(name string) *TypeBinding {
return &TypeBinding{
name: name,
}
}
func (t *TypeBinding) Name() string {
return t.name
}
func (t *TypeBinding) Bind(r *http.Request, i interface{}) error {
ttype := r.URL.Query().Get(t.name)
ii := i.(*QueryParams)
ii.Type = strings.Split(ttype, ",")
return nil
}
type QueryParams struct {
Type []string `url:"type"`
}
func ggin() {
router := gin.Default()
typeBinding := NewTypeBinding("type")
var opt QueryParams
router.GET("/", func(c *gin.Context) {
if err := c.MustBindWith(&opt, typeBinding); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "couldn't bind query params"})
return
}
log.Printf("type: %v", opt.Type)
c.String(http.StatusOK, "type: %s", opt.Type)
})
router.Run(":8080")
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论