News API API in Go

News API API in Go

This guide shows you how to integrate the News API into your Go application. Headlines and articles from 80,000+ worldwide news sources.

Prerequisites

  • Go installed on your system
  • An News API API key (sign up at https://newsapi.org)
  • Basic familiarity with HTTP APIs

Installation

go mod init myapp
go get github.com/go-resty/resty/v2

Basic Usage

package main

import (
    "fmt"
    "io"
    "net/http"
    "os"
)

func main() {
    apiKey := os.Getenv("API_KEY")
    if apiKey == "" {
        apiKey = "YOUR_API_KEY"
    }
    baseURL := "https://api.newsapi.org"

    req, _ := http.NewRequest("GET", baseURL+"/v1/resources", nil)
    req.Header.Set("Authorization", "Bearer "+apiKey)
    req.Header.Set("Content-Type", "application/json")

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

    body, _ := io.ReadAll(resp.Body)
    fmt.Println("Status:", resp.Status)
    fmt.Println(string(body))
}

Error Handling

package main

import (
    "fmt"
    "io"
    "net/http"
    "os"
    "time"
)

func callAPIWithRetry(url, apiKey string, maxRetries int) ([]byte, error) {
    var lastErr error
    for attempt := 0; attempt < maxRetries; attempt++ {
        req, _ := http.NewRequest("GET", url, nil)
        req.Header.Set("Authorization", "Bearer "+apiKey)

        resp, err := http.DefaultClient.Do(req)
        if err != nil {
            lastErr = err
            time.Sleep(time.Duration(1<<attempt) * time.Second)
            continue
        }

        if resp.StatusCode == 429 {
            retryAfter := resp.Header.Get("Retry-After")
            fmt.Println("Rate limited. Retry-After:", retryAfter)
            resp.Body.Close()
            time.Sleep(60 * time.Second)
            continue
        }

        if resp.StatusCode >= 400 {
            body, _ := io.ReadAll(resp.Body)
            resp.Body.Close()
            lastErr = fmt.Errorf("HTTP %d: %s", resp.StatusCode, string(body))
            time.Sleep(time.Duration(1<<attempt) * time.Second)
            continue
        }

        body, err := io.ReadAll(resp.Body)
        resp.Body.Close()
        return body, err
    }
    return nil, lastErr
}

func main() {
    apiKey := os.Getenv("API_KEY")
    body, err := callAPIWithRetry("https://api.newsapi.org/v1/resources", apiKey, 3)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Println(string(body))
}

Advanced Usage

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "os"
    "time"
)

type NewsapiClient struct {
    APIKey  string
    BaseURL string
    HTTP    *http.Client
}

func NewClient(apiKey, baseURL string) *NewsapiClient {
    return &NewsapiClient{
        APIKey:  apiKey,
        BaseURL: baseURL,
        HTTP:    &http.Client{Timeout: 30 * time.Second},
    }
}

func (c *NewsapiClient) do(method, path string, body interface{}) ([]byte, error) {
    var reqBody io.Reader
    if body != nil {
        jsonData, _ := json.Marshal(body)
        reqBody = bytes.NewBuffer(jsonData)
    }
    req, _ := http.NewRequest(method, c.BaseURL+path, reqBody)
    req.Header.Set("Authorization", "Bearer "+c.APIKey)
    req.Header.Set("Content-Type", "application/json")

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

    return io.ReadAll(resp.Body)
}

func (c *NewsapiClient) ListResources() ([]byte, error) {
    return c.do("GET", "/v1/resources", nil)
}

func (c *NewsapiClient) CreateResource(data map[string]interface{}) ([]byte, error) {
    return c.do("POST", "/v1/resources", data)
}

func main() {
    client := NewClient(os.Getenv("API_KEY"), "https://api.newsapi.org")
    resources, err := client.ListResources()
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Println(string(resources))
}

Best Practices

  • Store your API key in an environment variable, never in source code
  • Implement retry logic with exponential backoff for 429 and 5xx errors
  • Set reasonable timeouts (10-30 seconds) for all API calls
  • Log request IDs from response headers for debugging
  • Cache responses where appropriate to reduce API calls

Other languages