How to Build a REST Client in Go (With Real Code Examples)

If you’re working with REST APIs, knowing how to build your own API client is essential. In this guide, we’ll walk through how to write a REST client in Go (Golang) using only the standard library—no third-party dependencies required.

Why Go? Because it’s fast, simple, and comes with a robust HTTP package right out of the box. Whether you’re fetching data, authenticating requests, or customizing headers, Go makes it straightforward.

What You’ll Learn

  • Using Go’s built-in HTTP client
  • Working with request and response objects
  • Writing your own reusable API client

Prerequisites

  • Go compiler installed (at least version 1.18 or higher recommended).
  • A basic understanding of HTTP methods (GET, POST, PUT, DELETE).

Making Your First HTTP Request in Go

Go’s net/http package lets you send requests with minimal code. For example, here’s how to make a simple GET request:

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

body, err := io.ReadAll(resp.Body)
if err != nil {
    log.Fatal(err)
}
fmt.Println(string(body))

This snippet:

  • Sends a GET request
  • Reads the response body
  • Handles potential errors (a must in Go)

Customizing the HTTP Client

The default client works fine for quick tests, but for production you’ll usually want to set timeouts and control transport options.

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

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

Here we set a 10-second timeout. If the server doesn’t respond in time, the request is canceled automatically.

You can also customize:

  • Max connections
  • Idle connection time
  • Proxy settings

Working with Request Objects

Sometimes http.Get or http.Post isn’t enough. For example, you might need to add headers or send JSON data. That’s where http.NewRequest comes in:

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

req.Header.Set("User-Agent", "my-go-client")
resp, err := client.Do(req)

With Request, you can:

  • Add headers (User-Agent, Content-Type, Authorization)
  • Send JSON bodies
  • Handle cookies

Example: Adding Authorization

Many REST APIs require a token. Here’s how you’d add one:

req.Header.Set("Authorization", "Bearer YOUR_TOKEN_HERE")

That one line authenticates your request to the server.


Handling Responses

When the server replies, Go gives you a Response object that contains:

  • StatusCode (200, 404, 500, etc.)
  • Headers (Content-Type, Cache-Control, etc.)
  • Response body

Important: Always close the response body:

defer resp.Body.Close()

Skipping this can lead to memory leaks or hanging connections.


Building a Reusable API Client in Go

Instead of writing raw requests every time, you can package everything into a reusable client.

Here’s a minimal structure:

type Client struct {
    baseURL string
    token   string
}

func NewClient(baseURL string) *Client {
    return &Client{ baseURL: baseURL }
}

From here, you can add methods for login, fetching data, and sending custom requests. Example:

func (c *Client) Login(user, password string) error {
    data := map[string]string{
        "user": user,
        "password": password,
    }
    body, _ := json.Marshal(data)

    req, _ := http.NewRequest("POST", c.baseURL+"/login", bytes.NewBuffer(body))
    req.Header.Set("Content-Type", "application/json")

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

    if resp.StatusCode != http.StatusOK {
        return errors.New("invalid login")
    }

    responseBody, _ := io.ReadAll(resp.Body)
    var result map[string]string
    json.Unmarshal(responseBody, &result)

    c.token = result["token"]
    return nil
}

Now your client can log in and save the token, ready to be reused in other requests.


Summary

  • Go’s http package makes it easy to send HTTP requests without external libraries.
  • Use http.NewRequest when you need more control.
  • Always close response bodies.
  • Wrapping everything into a custom client helps organize your code for real-world projects.

With this foundation, you can start building powerful Go clients that handle authentication, JSON parsing, and API interactions like a pro.

Hello! I'm a gaming enthusiast, a history buff, a cinema lover, connected to the news, and I enjoy exploring different lifestyles. I'm Yaman Şener/trioner.com, a web content creator who brings all these interests together to offer readers in-depth analyses, informative content, and inspiring perspectives. I'm here to accompany you through the vast spectrum of the digital world.

Leave a Reply

Your email address will not be published. Required fields are marked *