将URL.Query(切片映射)转换为struct golang

时间:2016-11-12 16:11:31

标签: go struct

从标准库URL.Query()到结构的直接映射真是太棒了。

Query()会返回如下地图: map[a:[aaaa] b:[bbbb] c:[cccc]]

结构看起来像:

type Thing struct {
    A    string
    B    string
    C    string
}
  • 我不知道为什么URL.Query会返回一个包含数组元素的地图。 (嗯..我知道why但是GET不太可能有重复的参数。

5 个答案:

答案 0 :(得分:3)

请在下面找到直接在golang结构中解析get query params然后将结构作为响应发送回来的完整示例

package main

import (
    "log"
    "net/http"
    "encoding/json"
    "github.com/gorilla/schema"
)

var decoder  = schema.NewDecoder()

type EmployeeStruct struct {
    MemberId         string `schema:"memberId"`
    ActivityType     string `schema:"activityType"`
    BusinessUnitCode int    `schema:"businessUnitCode"`
}

func GetEmployee(w http.ResponseWriter, r *http.Request) {
    var employeeStruct EmployeeStruct

    err := decoder.Decode(&employeeStruct, r.URL.Query())
    if err != nil {
        log.Println("Error in GET parameters : ", err)
    } else {
        log.Println("GET parameters : ", employeeStruct)
    }

    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(employeeStruct)
}

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/GetEmployee", GetEmployee)
    log.Fatal(http.ListenAndServe(":8080", mux))
}

执行步骤&测试(假设您在 employee.go 中保存了以上代码):

第1步:go run employee.go

第2步:在浏览器http://localhost:8080/GetEmployee?memberId=123&activityType=Call&businessUnitCode=56

中打开

第3步:您应该在浏览器窗口中获得以下响应

{
    "MemberId": "123",
    "ActivityType": "Call",
    "BusinessUnitCode": 56
}

第4步:在控制台上,您应该看到

GET parameters :  {123 Call 56}

答案 1 :(得分:1)

正如@ mh-cbon所指出的那样gorilla schema是最终解决方案。

而是从URL属性获取queryParams。

func handleRequest(w http.ResponseWriter, r *http.Request) {
    queryString := r.URL.Query()
    //...parsing the Values -> map[string][]string
}

gorilla架构的方法是将r.PostForm发送到解码函数。

func handleRequest(w http.ResponseWriter, r *http.Request) {
    err := decoder.Decode(person, r.PostForm)
    //...using reflect each struct's property can be called using 
    // the PostForm(url string, data url.Values) signature

    fmt.Print(person.GoodJobGorilla)
}

答案 2 :(得分:0)

您可以使用优美的“ Echo”软件包。我写了一些代码作为示例,并带有不言自明的注释

 package main

 import (
     "log"
     "github.com/labstacks/echo"
)

// Declare your struct with form: "" tag
type Employee struct {
    MemberId         string `form:"memberId"`
    ActivityType     string `form:"activityType"`
    BusinessUnitCode int    `form:"businessUnitCode"`
}

// Your handlers should look like this method 
// Which takes an echo.Context and returns an error
func GetEmployee(ctx echo.Context) error{
    var employee Employee
    // With Bind, you can get the Post Body or query params from http.Request
    // that is wrapped by echo.Context here 
    if err := ctx.Bind(&employee);err != nil {
        return err
    } 

// now you can use your struct , e.g
return ctx.json(200,employee.MemberId)
}

// now use the handler in your main function or anywhere you need
func main() {
    e := echo.New
    e.Get("/employee", GetEmployee)
    log.Fatal(e.Start(":8080"))
}

答案 3 :(得分:0)

示例:

send()

需要的网址编码为:

fmt.Printf("put val %v in channel\n", i)

并且可以使用filters={"reference":["docker.io/library/alpine:latest"]}

filters=%7B%22reference%22%3A%5B%22docker.io%2Flibrary%2Falpine%3Alatest%22%5D%7D

答案 4 :(得分:0)

我专门为解决这个问题编写了一个 Go 包 ggicci/httpin。不仅用于查询,还用于解码来自 HTTP 标头的数据。举个例子:

type Authorization struct {
    // Decode from multiple sources, the former with higher priority
    Token string `in:"form=access_token;header=x-api-token;required"`
}

type Pagination struct {
    Page int `in:"form=page"`

    // Decode from multiple keys in the same source, the former with higher priority
    PerPage int `in:"form=per_page,page_size"`
}

type ListUsersInput struct {
    Gender   string `in:"form=gender"`
    AgeRange []int  `in:"form=age_range"`
    IsMember bool   `in:"form=is_member"`

    Pagination    // Embedded field works
    Authorization // Embedded field works
}

func ListUsers(rw http.ResponseWriter, r *http.Request) {
    inputInterface, err := httpin.New(ListUsersInput{}).Decode(r)
    if err != nil {
        // Error occurred, `err` can be type of *httpin.InvalidFieldError
        // Do sth.
        return
    }

    input := interfaceInput.(*ListUsersInput)
    // Do sth.
}

我确实希望这个库可以节省每个人用 Go 编写 API 的时间。