Skip to main content

default

Introduced in v0.8.0.

default is a directive executor who populates unset fields to their default values while decoding, and populates zero fields to their default values while encoding.

  • unset fields: fields that have not been set by former directives.
  • zero fields: values are zero values, such as 0, "", false, nil, [], map[], struct{}.

Signature

Name: "default"
Args: VAL1 [,VAL2 [,VAL3, ...]]
caution

For an array type of value, you can use comma to separate the items in the array. So the presence of comma in an array item can lead to unexpected behavior.

Decoding

default will examine if the field has already been set by former directives. If not, it will set the field to the given value.

Usage

type ListTasksQuery struct {
Page int `in:"query=page;default=1"`
PerPage int `in:"query=per_page;default=20"`
StateList []string `in:"query=state;default=pending,running"`
}
RequestListTasksQuery
GET /tasks?page=4&perPage=10&state=failed&state=succeeded
{
Page: 4,
PerPage: 10,
StateList: []string{"failed", "succeeded"},
}
GET /tasks
{
Page: 1,
PerPage: 20,
StateList: []string{"pending", "running"},
}

Runable Example

package main

import (
"fmt"
"net/http"
"net/http/httptest"

"github.com/ggicci/httpin"
"github.com/go-chi/chi/v5"
)

type ListTasksQuery struct {
Page int `in:"query=page;default=1"`
PerPage int `in:"query=per_page;default=20"`
StateList []string `in:"query=state;default=pending,running"`
}

func ListTasks(rw http.ResponseWriter, r *http.Request) {
input := r.Context().Value(httpin.Input).(*ListTasksQuery)
fmt.Printf("input: %#v\n", input)
}

func main() {
router := chi.NewRouter()
router.With(
httpin.NewInput(ListTasksQuery{}),
).Get("/tasks", ListTasks)

r, _ := http.NewRequest("GET", "/tasks?page=0", nil)

rw := httptest.NewRecorder()
router.ServeHTTP(rw, r)

}

Output:

input: &main.ListTasksQuery{Page:0, PerPage:20, StateList:[]string{"pending", "running"}}

Encoding

default will examine if the field is a zero value. If so, it will set the field to the given value.

note

Since httpin runs the directives in the order of their appearance in the struct, you should always define the order of the directives based on decoding requirements, default should be placed after directives like query and path that set the field values.

In order to make it works for encoding as well, httpin will reorder the directives internally for encoding. The final order of directives will be:

  1. required
  2. default
  3. other directives

For example, the above struct will be reordered to:

type ListTasksQuery struct {
Page int `in:"default=1;query=page"`
PerPage int `in:"default=20;query=per_page"`
}

Runable Example

package main

import (
"fmt"
"net/http/httputil"

"github.com/ggicci/httpin"
)

type ListTasksQuery struct {
Page int `in:"query=page;default=1"`
PerPage int `in:"query=per_page;default=20"`
StateList []string `in:"query=state;default=pending,running"`
}

func main() {
input := &ListTasksQuery{Page: 3}
r, _ := httpin.NewRequest("GET", "/tasks", input)
data, _ := httputil.DumpRequest(r, true)
fmt.Printf("%s\n", data)
}

Output:

GET /tasks?page=3&per_page=20&state=pending&state=running HTTP/1.1