Request

HTTP Methods

GET

resp, err := http.Get("https://example.com")
if err != nil {
	return err
}
defer resp.Body.Close()

http.Get returns an *http.Response. Always close resp.Body when finished. Go Packages

POST

body := strings.NewReader(`{"name":"Ben"}`)

req, err := http.NewRequest(http.MethodPost, "https://example.com/users", body)
if err != nil {
	return err
}

req.Header.Set("Content-Type", "application/json")

resp, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer resp.Body.Close()

Shorthand:

resp, err := http.Post(
	"https://example.com/users",
	"application/json",
	strings.NewReader(`{"name":"Ben"}`),
)

PUT

body := strings.NewReader(`{"name":"Benjamin"}`)

req, err := http.NewRequest(http.MethodPut, "https://example.com/users/1", body)
if err != nil {
	return err
}

req.Header.Set("Content-Type", "application/json")

resp, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer resp.Body.Close()

DELETE

req, err := http.NewRequest(http.MethodDelete, "https://example.com/users/1", nil)
if err != nil {
	return err
}

resp, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer resp.Body.Close()

Method constants

http.MethodGet
http.MethodPost
http.MethodPut
http.MethodPatch
http.MethodDelete

Check the status code

if resp.StatusCode != http.StatusOK {
	return fmt.Errorf("unexpected status: %s", resp.Status)
}

Common constants:

http.StatusOK          // 200
http.StatusNotFound    // 404
http.StatusBadRequest  // 400

Read the body as bytes

body, err := io.ReadAll(resp.Body)
if err != nil {
	return err
}

fmt.Println(string(body))

Decode JSON

type User struct {
	ID   int    `json:"id"`
	Name string `json:"name"`
}

var user User

err = json.NewDecoder(resp.Body).Decode(&user)
if err != nil {
	return err
}

Complete example

func GetUser() (User, error) {
	resp, err := http.Get("https://example.com/user")
	if err != nil {
		return User{}, fmt.Errorf("get user: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return User{}, fmt.Errorf("unexpected status: %s", resp.Status)
	}

	var user User

	if err := json.NewDecoder(resp.Body).Decode(&user); err != nil {
		return User{}, fmt.Errorf("decode user: %w", err)
	}

	return user, nil
}

Request with headers

http.Get cannot directly add headers. Create a request instead:

req, err := http.NewRequest(http.MethodGet, "https://example.com", nil)
if err != nil {
	return err
}

req.Header.Set("Authorization", "Bearer token")
req.Header.Set("Accept", "application/json")

resp, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer resp.Body.Close()

Production client with timeout

client := &http.Client{
	Timeout: 5 * time.Second,
}

resp, err := client.Get("https://example.com")