Skip to main content
โšก Calmops

HTTP Client and Server in Go

HTTP Client and Server in Go

Go’s standard library provides powerful HTTP capabilities. Building web servers and clients is straightforward and efficient.

HTTP Server

Basic HTTP Server

package main

import (
    "fmt"
    "net/http"
)

func helloHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, World!")
}

func main() {
    http.HandleFunc("/", helloHandler)
    http.ListenAndServe(":8080", nil)
}

Multiple Routes

package main

import (
    "fmt"
    "net/http"
)

func homeHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Home Page")
}

func aboutHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "About Page")
}

func main() {
    http.HandleFunc("/", homeHandler)
    http.HandleFunc("/about", aboutHandler)
    http.ListenAndServe(":8080", nil)
}

JSON Response

package main

import (
    "encoding/json"
    "net/http"
)

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

func userHandler(w http.ResponseWriter, r *http.Request) {
    user := User{ID: 1, Name: "Alice", Age: 30}

    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(user)
}

func main() {
    http.HandleFunc("/user", userHandler)
    http.ListenAndServe(":8080", nil)
}

Request Methods

package main

import (
    "encoding/json"
    "fmt"
    "net/http"
)

func apiHandler(w http.ResponseWriter, r *http.Request) {
    switch r.Method {
    case http.MethodGet:
        fmt.Fprintf(w, "GET request")
    case http.MethodPost:
        var data map[string]interface{}
        json.NewDecoder(r.Body).Decode(&data)
        fmt.Fprintf(w, "POST request: %v", data)
    case http.MethodPut:
        fmt.Fprintf(w, "PUT request")
    case http.MethodDelete:
        fmt.Fprintf(w, "DELETE request")
    default:
        w.WriteHeader(http.StatusMethodNotAllowed)
    }
}

func main() {
    http.HandleFunc("/api", apiHandler)
    http.ListenAndServe(":8080", nil)
}

HTTP Client

Basic HTTP Request

package main

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

func main() {
    resp, err := http.Get("https://api.example.com/data")
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }

    fmt.Println(string(body))
}

POST Request

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "net/http"
)

func main() {
    data := map[string]string{
        "name": "Alice",
        "age":  "30",
    }

    jsonData, _ := json.Marshal(data)

    resp, err := http.Post(
        "https://api.example.com/users",
        "application/json",
        bytes.NewBuffer(jsonData),
    )
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    defer resp.Body.Close()

    fmt.Println("Status:", resp.Status)
}

Custom Request

package main

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

func main() {
    req, err := http.NewRequest("GET", "https://api.example.com/data", nil)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }

    // Add headers
    req.Header.Add("Authorization", "Bearer token123")
    req.Header.Add("User-Agent", "MyApp/1.0")

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

    body, _ := ioutil.ReadAll(resp.Body)
    fmt.Println(string(body))
}

Middleware

Simple Middleware

package main

import (
    "fmt"
    "net/http"
)

func loggingMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        fmt.Printf("Request: %s %s\n", r.Method, r.URL.Path)
        next.ServeHTTP(w, r)
    })
}

func helloHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello!")
}

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/", helloHandler)

    handler := loggingMiddleware(mux)
    http.ListenAndServe(":8080", handler)
}

Best Practices

โœ… Good: Always Close Response Body

// DO: Always close response body
resp, err := http.Get(url)
if err != nil {
    return err
}
defer resp.Body.Close()

body, _ := ioutil.ReadAll(resp.Body)

โŒ Bad: Forget to Close

// DON'T: Forget to close response body
resp, _ := http.Get(url)
body, _ := ioutil.ReadAll(resp.Body)

โœ… Good: Check Status Code

// DO: Check response status
resp, _ := http.Get(url)
if resp.StatusCode != http.StatusOK {
    return fmt.Errorf("unexpected status: %d", resp.StatusCode)
}

โœ… Good: Set Timeouts

// DO: Set timeouts for HTTP client
client := &http.Client{
    Timeout: 10 * time.Second,
}
resp, err := client.Get(url)

Summary

Go’s HTTP support provides:

  1. Simple server creation with http.ListenAndServe
  2. Easy client requests with http.Get, http.Post
  3. Middleware support for request processing
  4. JSON encoding/decoding built-in
  5. Efficient handling of concurrent requests

These features make Go ideal for web development.

Comments