Back to Blog

REST API Calls Without External Libraries: Go net/http Tutorialn #31

Sandy LaneSandy Lane

Video: REST API Calls Without External Libraries: Go net/http Tutorialn #31 by Taught by Celeste AI - AI Coding Coach

Watch full page →

REST API Calls Without External Libraries: Go net/http Tutorial

Discover how to perform REST API calls in Go using only the standard net/http package, eliminating the need for external libraries. This tutorial covers making GET and POST requests, handling JSON data, customizing HTTP clients, and safely working with query parameters and headers.

Code

package main

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

// User represents JSON data with struct tags for serialization
type User struct {
  Name  string `json:"name"`
  Email string `json:"email"`
}

func main() {
  // Simple GET request
  resp, err := http.Get("https://jsonplaceholder.typicode.com/posts/1")
  if err != nil {
    panic(err)
  }
  defer resp.Body.Close() // ensure body is closed

  fmt.Println("Status Code:", resp.StatusCode)
  fmt.Println("Content-Type:", resp.Header.Get("Content-Type"))

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

  // POST request with JSON payload
  user := User{Name: "Alice", Email: "alice@example.com"}
  jsonData, err := json.Marshal(user)
  if err != nil {
    panic(err)
  }

  respPost, err := http.Post("https://jsonplaceholder.typicode.com/users", "application/json", bytes.NewBuffer(jsonData))
  if err != nil {
    panic(err)
  }
  defer respPost.Body.Close()

  var createdUser User
  if err := json.NewDecoder(respPost.Body).Decode(&createdUser); err != nil {
    panic(err)
  }
  fmt.Printf("Created User: %+v\n", createdUser)

  // Custom client with timeout and custom headers
  client := &http.Client{Timeout: 5 * time.Second}

  // Build URL with query parameters safely
  baseURL, _ := url.Parse("https://jsonplaceholder.typicode.com/posts")
  params := url.Values{}
  params.Add("userId", "1")
  baseURL.RawQuery = params.Encode()

  req, err := http.NewRequest("GET", baseURL.String(), nil)
  if err != nil {
    panic(err)
  }
  req.Header.Set("Accept", "application/json")
  req.Header.Set("User-Agent", "Go-http-client/1.1")

  respCustom, err := client.Do(req)
  if err != nil {
    panic(err)
  }
  defer respCustom.Body.Close()

  var posts []map[string]any
  if err := json.NewDecoder(respCustom.Body).Decode(&posts); err != nil {
    panic(err)
  }
  fmt.Printf("Posts by user 1: %d items\n", len(posts))
}

Key Points

  • Use http.Get and http.Post for simple REST API calls without extra dependencies.
  • Always defer resp.Body.Close() to prevent resource leaks after reading response bodies.
  • Serialize and deserialize JSON using json.Marshal, json.Unmarshal, and json.NewDecoder with struct tags.
  • Create custom HTTP clients with timeouts and use http.NewRequest to set headers and query parameters safely.
  • Use url.Values to encode query parameters and map[string]any for flexible JSON decoding.