Basic Go HTTP Requests

September 01, 2019

The http.Client type has two kinds of method attached to it: Do and everything else. The everything else category includes:

The above are preconfigured and cannot be modified, but are easy to use:

package main

import "net/http"

response, _ := http.Get("")
defer resp.Body.Close()
// Do something with the response

Under the hood, this is calling what you’ll likely be using yourself: http.NewRequest and http.Do.

These allow you to customize the structure of your requests:

package main

import (

// Create an HTTP client with a connection timeout
var client = &http.Client{
  Timeout: time.Second * 5,

request, err := http.NewRequest("GET", "", nil)
if err != nil {
  return "", err

// Add "?id=1"
queryString := url.Values{}
queryString.Add("id", 1)
request.URL.RawQuery = queryString.Encode()

response, _ := client.Do(request)
defer resp.Body.Close()
// More something here

Posting a Form

Here’s how you can POST a form using http.NewRequest and http.Do:

package main

import (

func main() {
  // We define our own client so we can play with things
	client := &http.Client{
		Timeout: 5 * time.Second,

  // We start by building a query string (e.g. param1=value&param2=value)
	body := url.Values{}
	body.Add("param1", "value") // Add adds a new header. To update, we'd use Set
	body.Add("param2", "value")
	body.Add("param3", "value")

  // Build the request
	req, _ := http.NewRequest("POST", "", strings.NewReader(body.Encode())) // We need to use strings.NewReader to satisfy the io.Reader type

  // Add a few headers. Content-Length is automatically populated.
	req.Header.Add("Test", "Value")
	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")

  // Finally we send the request
	resp, _ := client.Do(req)
	defer resp.Body.Close()
	// Something happens