03 How To Used Query Parameter in Golang
Introduction to Query Parameters
Query parameters are one of the features of http that we usually use to send data from the client to the server. This parameter query is placed in the URL of the endpoint that we have created. To add query parameters, we can use ?=name=value in our website URL.
Package url.URL
The package that we use to recognize query parameters is url.URL in the request parameter. From this URL we can retrieve query parameter data sent from the client using the Query() method with map type data returns.
For example, we will create a handler that accepts parameters from the client as below.
1func SayHelloParameterHandler(w http.ResponseWriter, r *http.Request) {
2 name := r.URL.Query().Get("name")
3 if name == "" {
4 fmt.Fprint(w, "Hello")
5 } else {
6 fmt.Fprintf(w, "Hello %s", name)
7 }
8}We need to prove this function works well, we need to add a unit test as below.
1func TestSayHelloParameterHandler(t *testing.T) {
2 type args struct {
3 name string
4 }
5 tests := []struct {
6 name string
7 args args
8 want string
9 }{
10 {
11 name: "success return response with name",
12 args: args{
13 name: "santekno",
14 },
15 want: "Hello santekno",
16 },
17 {
18 name: "success return response without name",
19 args: args{
20 name: "",
21 },
22 want: "Hello",
23 },
24 }
25 for _, tt := range tests {
26 t.Run(tt.name, func(t *testing.T) {
27 request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://localhost/say?name=%s", tt.args.name), nil)
28 recorder := httptest.NewRecorder()
29 SayHelloParameterHandler(recorder, request)
30
31 response := recorder.Result()
32 body, _ := io.ReadAll(response.Body)
33 bodyString := string(body)
34
35 if !reflect.DeepEqual(bodyString, tt.want) {
36 t.Errorf("response = %v, want %v", bodyString, tt.want)
37 }
38 })
39 }
40}Multiple Query Parameters
When we want to receive more than one parameter sent by the client, this URL specification can support sending many parameters to the server by using the & sign followed by querying the next parameter.
For example, the client sends two query parameters and will later be received by the server with the handler below.
1func MultipleParameterHandler(w http.ResponseWriter, r *http.Request) {
2 firstName := r.URL.Query().Get("first_name")
3 lastName := r.URL.Query().Get("last_name")
4 if firstName == "" && lastName == "" {
5 fmt.Fprint(w, "Hello")
6 } else {
7 fmt.Fprintf(w, "Hello %s %s", firstName, lastName)
8 }
9}Let’s try to test the results of the function we created above by creating the unit test below.
1func TestMultipleParameterHandler(t *testing.T) {
2 type args struct {
3 firstName string
4 lastName string
5 }
6 tests := []struct {
7 name string
8 args args
9 want string
10 }{
11 {
12 name: "success return response with name",
13 args: args{
14 firstName: "Santekno",
15 lastName: "Inc",
16 },
17 want: "Hello Santekno Inc",
18 },
19 {
20 name: "success return response without name",
21 args: args{
22 firstName: "",
23 lastName: "",
24 },
25 want: "Hello",
26 },
27 }
28 for _, tt := range tests {
29 t.Run(tt.name, func(t *testing.T) {
30 request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://localhost/say?first_name=%s&last_name=%s", tt.args.firstName, tt.args.lastName), nil)
31 recorder := httptest.NewRecorder()
32 MultipleParameterHandler(recorder, request)
33
34 response := recorder.Result()
35 body, _ := io.ReadAll(response.Body)
36 bodyString := string(body)
37
38 if !reflect.DeepEqual(bodyString, tt.want) {
39 t.Errorf("response = %v, want %v", bodyString, tt.want)
40 }
41 })
42 }
43}Multiple Value Query Parameters
We can actually parse the query parameter URL query and store it in the type map[string][]string. This means that in one key query parameter we can enter several values. How to? by adding a name parameter with the same name but different values, for example:
1name=Santekno&name=IhsanPreviously we used the Get() method to get the data, because currently the condition is multiple values so we cannot use this method. So, there are other ways that we can retrieve this data.
1func MultipleParameterValueHandler(w http.ResponseWriter, r *http.Request) {
2 query := r.URL.Query()
3 names := query["name"]
4 if len(names) == 0 {
5 fmt.Fprint(w, "Hello")
6 } else {
7 fmt.Fprintf(w, "Hello %s", strings.Join(names, " "))
8 }
9}We try to do a test by creating a unit test to ensure the data matches the parameters sent.
1func TestMultipleParameterValueHandler(t *testing.T) {
2 type args struct {
3 name []string
4 }
5 tests := []struct {
6 name string
7 args args
8 want string
9 }{
10 {
11 name: "success return response with name",
12 args: args{
13 name: []string{"santekno", "ihsan"},
14 },
15 want: "Hello santekno ihsan",
16 },
17 }
18 for _, tt := range tests {
19 t.Run(tt.name, func(t *testing.T) {
20 request := httptest.NewRequest(http.MethodGet, fmt.Sprintf("http://localhost/say?name=%s&name=%s", tt.args.name[0], tt.args.name[1]), nil)
21 recorder := httptest.NewRecorder()
22 MultipleParameterValueHandler(recorder, request)
23
24 response := recorder.Result()
25 body, _ := io.ReadAll(response.Body)
26 bodyString := string(body)
27
28 if !reflect.DeepEqual(bodyString, tt.want) {
29 t.Errorf("response = %v, want %v", bodyString, tt.want)
30 }
31 })
32 }
33}