query
query is a directive executor who decodes/encodes a field from/to URL querystring parameters, i.e. http.Request.URL.Query().
Signature
Name: "query"
Args: KEY1 [,KEY2 [,KEY3, ...]]
Decoding
query will examine values of the keys one by one (KEY1 -> KEY2 -> ...) from the URL querystring, the first non-empty value will be used to set the corresponding field of the input struct.
Usage
type ListUsersInput struct {
	IsMember bool  `in:"query=is_member"`
	AgeRange []int `in:"query=age_range[],age_range"`
}
| Request (URL query) | ListUsersInput | 
|---|---|
 |  | 
 |  | 
 |  | 
Runable Example
package main
import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"github.com/ggicci/httpin"
	"github.com/go-chi/chi/v5"
)
type ListUsersInput struct {
	IsMember bool  `in:"query=is_member"`
	AgeRange []int `in:"query=age_range[],age_range"`
}
func ListUsers(rw http.ResponseWriter, r *http.Request) {
	input := r.Context().Value(httpin.Input).(*ListUsersInput)
	fmt.Printf("input: %#v\n", input)
}
func main() {
	router := chi.NewRouter()
	router.With(
		httpin.NewInput(ListUsersInput{}),
	).Get("/users", ListUsers)
	r, _ := http.NewRequest("GET", "/users?is_member=1&age_range=18&age_range=60", nil)
	rw := httptest.NewRecorder()
	router.ServeHTTP(rw, r)
}
Output:
input: &main.ListUsersInput{IsMember:true, AgeRange:[]int{18, 60}}
Encoding
query will encode the field to the first key, i.e. KEY1, results in ?KEY1=VALUE.
Runable Example
package main
import (
	"fmt"
	"net/http/httputil"
	"github.com/ggicci/httpin"
)
type ListUsersInput struct {
	IsMember bool  `in:"query=is_member"`
	AgeRange []int `in:"query=age_range[],age_range"`
}
func main() {
	input := &ListUsersInput{
		IsMember: true,
		AgeRange: []int{18, 60},
	}
	r, _ := httpin.NewRequest("GET", "/users", input)
	data, _ := httputil.DumpRequest(r, false)
	fmt.Printf("%s\n", data)
}
Output:
GET /users?age_range%5B%5D=18&age_range%5B%5D=60&is_member=true HTTP/1.1