Query
ctx.Request.Query provides access to the parameters of the current request URL query string.
The query parameters allow you to send additional information via the URL and are usually used for searches, filters, systems, paging and other navigation options.
For example, in the next URL the parameter page contains the value 2:
/products?page=2 You can consult it by ctx.Request.Query:
func GET(ctx *gox.Context) gox.Page {
page, ok := ctx.Request.Query.Get("page")
if !ok {
page = "1"
}
return <p>Page {{ page }}</p>
} ctx.Request.Query It is a read-only collection. Its values are obtained from the URL query string and cannot be modified from the request.
Structure
ctx.Request.Query provides the following methods:
Query
{
Get(key string) (string, bool)
GetAll(key string) ([]string, bool)
Has(key string) bool
IsEmpty() bool
Count() int
Keys() []string
Values() []string
Entries() map[string][]string
} Methods
Get()
Returns the first value associated with a parameter and indicates if the parameter exists.
Firma:func (Query) Get(key string) (string, bool)
The second value returned is true when the parameter exists and contains at least one value.
When the parameter does not exist, it returns an empty string and false.
func GET(ctx *gox.Context) gox.Page {
// URL:
// /products?page=2
page, ok := ctx.Request.Query.Get("page")
// page == "2"
// ok == true
return <p>Page {{ page }}</p>
} When a parameter does not exist:
func GET(ctx *gox.Context) gox.Page {
// URL:
// /products
page, ok := ctx.Request.Query.Get("page")
if !ok {
page = "1"
}
// page == "1"
return <p>Page {{ page }}</p>
} When the same parameter appears several times, Get() returns only the first value.
func GET(ctx *gox.Context) gox.Page {
// URL:
// /articles?tag=go&tag=web
tag, ok := ctx.Request.Query.Get("tag")
// tag == "go"
// ok == true
return <p>{{ tag }}</p>
} Use GetAll() when you need to consult all the values associated with the parameter.
GetAll()
Returns all values associated with a parameter and indicates if the parameter exists.
Firma:func (Query) GetAll(key string) ([]string, bool)
When the parameter does not exist or contains values, it returns nil and false.
func GET(ctx *gox.Context) gox.Page {
// URL:
// /articles?tag=go&tag=web&tag=backend
tags, ok := ctx.Request.Query.GetAll("tag")
if !ok {
return <p>No tags selected.</p>
}
// tags == []string{"go", "web", "backend"}
return <ul>
<:for tag range={{ tags }}>
<li>{{ tag }}</li>
</:for>
</ul>
} When the parameter does not exist:
func GET(ctx *gox.Context) gox.Page {
// URL:
// /articles
tags, ok := ctx.Request.Query.GetAll("tag")
// tags == nil
// ok == false
if !ok {
return <p>No tags selected.</p>
}
return <ul>
<:for tag range={{ tags }}>
<li>{{ tag }}</li>
</:for>
</ul>
} The returned slice is a separate copy. Modifying it does not change the original parameters of the request.
func GET(ctx *gox.Context) gox.Page {
// URL:
// /articles?tag=go&tag=web
tags, ok := ctx.Request.Query.GetAll("tag")
if !ok {
return <p>No tags selected.</p>
}
tags[0] = "modified"
original, _ := ctx.Request.Query.Get("tag")
// original == "go"
return <p>{{ original }}</p>
} Has()
It indicates if there is a parameter with at least one value.
Firma:func (Query) Has(key string) bool
func GET(ctx *gox.Context) gox.Page {
// URL:
// /products?featured=true
featured := ctx.Request.Query.Has("featured")
// featured == true
return <p>Featured: {{ featured }}</p>
} Has() is useful when you only need to check the existence of a parameter and do not need to check its value.
func GET(ctx *gox.Context) gox.Page {
// URL:
// /products?debug=true
if ctx.Request.Query.Has("debug") {
return <p>Debug mode enabled.</p>
}
return <p>Debug mode disabled.</p>
} When you also need the value, use it directly Get() to avoid consulting the collection twice.
func GET(ctx *gox.Context) gox.Page {
page, ok := ctx.Request.Query.Get("page")
if !ok {
page = "1"
}
return <p>Page {{ page }}</p>
} IsEmpty()
It indicates whether the collection does not contain parameters with values.
Firma:func (Query) IsEmpty() bool
func GET(ctx *gox.Context) gox.Page {
// URL:
// /products
if ctx.Request.Query.IsEmpty() {
return <p>No query parameters were provided.</p>
}
return <p>The request contains query parameters.</p>
} A URL without a query string produces an empty collection.
/products A URL with parameters produces a non-empty collection.
/products?page=2 Count()
Returns the amount of different parameters that contain at least one value.
Firma:func (Query) Count() int
Count() key account, not the total amount of values.
func GET(ctx *gox.Context) gox.Page {
// URL:
// /products?category=books&tag=go&tag=web
count := ctx.Request.Query.Count()
// count == 2
//
// Claves:
// category
// tag
return <p>Parameters: {{ count }}</p>
} Although tag appears twice, represents a single key within the collection.
category = ["books"]
tag = ["go", "web"] Keys()
Returns the names of all parameters that contain at least one value.
Firma:func (Query) Keys() []string
func GET(ctx *gox.Context) gox.Page {
// URL:
// /products?sort=price&category=books&page=2
keys := ctx.Request.Query.Keys()
// keys contiene:
// "category"
// "page"
// "sort"
return <ul>
<:for key range={{ keys }}>
<li>{{ key }}</li>
</:for>
</ul>
} Each key appears only once, even when the parameter contains several values.
func GET(ctx *gox.Context) gox.Page {
// URL:
// /articles?tag=go&tag=web&tag=backend
keys := ctx.Request.Query.Keys()
// keys == []string{"tag"}
return <p>Parameters: {{ len(keys) }}</p>
} The returned slice is a separate copy and can be modified without altering the request parameters.
Values()
Returns all values stored in the collection.
Firma:func (Query) Values() []string
The repeated parameter values are individually included in the result.
func GET(ctx *gox.Context) gox.Page {
// URL:
// /articles?page=2&tag=go&tag=web
values := ctx.Request.Query.Values()
// values contiene:
// "2"
// "go"
// "web"
return <ul>
<:for value range={{ values }}>
<li>{{ value }}</li>
</:for>
</ul>
} Values() only returns the values. It does not retain the relationship between each value and its key.
When you need to know the name of each parameter, use Entries().
func GET(ctx *gox.Context) gox.Page {
values := ctx.Request.Query.Values()
if len(values) == 0 {
return <p>No query values were provided.</p>
}
return <p>Values: {{ len(values) }}</p>
} The returned slice is a separate copy. Modifying it does not change the request parameters.
Entries()
Returns all parameters and their values as a map.
Firma:func (Query) Entries() map[string][]string
Each map key represents the name of a parameter and contains all its associated values.
func GET(ctx *gox.Context) gox.Page {
// URL:
// /articles?page=2&tag=go&tag=web
entries := ctx.Request.Query.Entries()
// entries["page"] == []string{"2"}
// entries["tag"] == []string{"go", "web"}
return <ul>
<:for tag range={{ entries["tag"] }}>
<li>{{ tag }}</li>
</:for>
</ul>
} You can visit all the entries in the collection:
func GET(ctx *gox.Context) gox.Page {
// URL:
// /products?category=books&sort=price&page=2
entries := ctx.Request.Query.Entries()
return <ul>
<:for key, values range={{ entries }}>
<li>
<strong>{{ key }}</strong>
<ul>
<:for value range={{ values }}>
<li>{{ value }}</li>
</:for>
</ul>
</li>
</:for>
</ul>
} Both the map and its slices are independent copies. Modifying them does not change the original parameters of the request.
func GET(ctx *gox.Context) gox.Page {
// URL:
// /articles?tag=go&tag=web
entries := ctx.Request.Query.Entries()
entries["tag"][0] = "modified"
entries["page"] = []string{"3"}
tag, _ := ctx.Request.Query.Get("tag")
hasPage := ctx.Request.Query.Has("page")
// tag == "go"
// hasPage == false
return <p>{{ tag }}</p>
} Full example
The following example uses query parameters to implement a search with filters, tags, ordering and paging.
func GET(ctx *gox.Context) gox.Page {
// Ejemplo:
// /products?search=laptop&category=electronics&tag=portable&tag=work&sort=price&page=2
search, _ := ctx.Request.Query.Get("search")
category, _ := ctx.Request.Query.Get("category")
tags, hasTags := ctx.Request.Query.GetAll("tag")
sort, hasSort := ctx.Request.Query.Get("sort")
page, hasPage := ctx.Request.Query.Get("page")
if !hasSort {
sort = "name"
}
if !hasPage {
page = "1"
}
return <main>
<h1>Products</h1>
<dl>
<dt>Search</dt>
<dd>{{ search }}</dd>
<dt>Category</dt>
<dd>{{ category }}</dd>
<dt>Sort</dt>
<dd>{{ sort }}</dd>
<dt>Page</dt>
<dd>{{ page }}</dd>
</dl>
<h2>Tags</h2>
<:if !hasTags>
<p>No tags selected.</p>
<:else>
<ul>
<:for tag range={{ tags }}>
<li>{{ tag }}</li>
</:for>
</ul>
</:if>
</main>
} Empty parameters
The new signature of Get() allows to distinguish between an absent parameter and a present parameter whose value is an empty string.
For example:
/products?page= produce:
func GET(ctx *gox.Context) gox.Page {
page, ok := ctx.Request.Query.Get("page")
// page == ""
// ok == true
return <p>Page: {{ page }}</p>
} Instead:
/products produce:
func GET(ctx *gox.Context) gox.Page {
page, ok := ctx.Request.Query.Get("page")
// page == ""
// ok == false
return <p>Page: {{ page }}</p>
} This difference makes it possible to validate correctly if the client omitted a parameter or sent it explicitly without value.
Value encoding
The reference parameters are decoded before they are stored in ctx.Request.Query.
For example:
/search?q=hello%20world can be consulted as:
func GET(ctx *gox.Context) gox.Page {
query, ok := ctx.Request.Query.Get("q")
if !ok {
return <p>No search provided.</p>
}
// query == "hello world"
return <p>{{ query }}</p>
} The special characters must be encoded correctly when building a URL.
Conversion of values
All values of ctx.Request.Query They're strings.
When you need to work with numbers, boolean, dates or other types, you must convert them and validate possible errors.
func GET(ctx *gox.Context) gox.Page {
pageText, ok := ctx.Request.Query.Get("page")
if !ok {
pageText = "1"
}
page, err := strconv.Atoi(pageText)
if err != nil || page < 1 {
return <p>Invalid page.</p>
}
return <p>Page {{ page }}</p>
} You must not assume that a value received from the URL contains the expected type or format.
Best practices
- Use
Get()when you only need the first value of a parameter. - Use
GetAll()when a parameter can appear several times. - Check the boolean value returned by
Get()andGetAll(). - Use
Has()when you only need to check for a parameter. - Define default values for optional parameters.
- Always value the values before using them.
- It explicitly converts numbers, booleans, dates and other types.
- Rejects values that do not belong to the set permitted by the application.
- It sets reasonable limits for parameters such as pages, quantities and sizes.
- Do not build database queries by directly focusing URL values.
- Do not use query parameters to send passwords, tokens or other confidential information.
- It uses clear, stable and consistent parameter names.
- Use
Values()when you only need to go through all the values. - Use
Entries()when you need to keep the relationship between the keys and their values.
To learn more about RequestSee your documentation. To learn more about URLSee your documentation. To learn more about FormSee your documentation. To learn more about RouteSee your documentation. To learn more about Context, check your documentation.