HTTP & Web Requests in Go
Building web servers and making HTTP requests
🌐 What is HTTP in Go?
Go's net/http package provides comprehensive tools for building web servers and making HTTP requests. Create REST APIs, web applications, and HTTP clients with ease and efficiency.
// Simple HTTP server example
package main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!")
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
Output:
Server running on http://localhost:8080
Response: Hello, World!
HTTP Operations in Go
HTTP Server
Create web servers and APIs
http.ListenAndServe(":8080", nil)
HTTP Client
Make requests to web services
resp, err := http.Get(url)
Routing
Handle different URL paths
http.HandleFunc("/api", handler)
Middleware
Add functionality to requests
http.Handle("/", middleware(handler))
🔹 Creating HTTP Server
Build a simple web server with multiple routes:
package main
import (
"encoding/json"
"fmt"
"net/http"
)
type User struct {
ID int `json:"id"`
Name string `json:"name"`
}
func homeHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Welcome to Go HTTP Server!")
}
func usersHandler(w http.ResponseWriter, r *http.Request) {
users := []User{
{ID: 1, Name: "Alice"},
{ID: 2, Name: "Bob"},
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(users)
}
func main() {
http.HandleFunc("/", homeHandler)
http.HandleFunc("/users", usersHandler)
fmt.Println("Server starting on :8080")
http.ListenAndServe(":8080", nil)
}
Output:
Server starting on :8080
GET / → Welcome to Go HTTP Server!
GET /users → [{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]
🔹 Making HTTP Requests
Send HTTP requests to external APIs:
package main
import (
"fmt"
"io"
"net/http"
"strings"
)
func main() {
// GET request
resp, err := http.Get("https://jsonplaceholder.typicode.com/posts/1")
if err != nil {
fmt.Println("Error:", err)
return
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println("GET Response:")
fmt.Println(string(body))
// POST request
jsonData := `{"title":"Go HTTP","body":"Learning HTTP requests","userId":1}`
resp, err = http.Post(
"https://jsonplaceholder.typicode.com/posts",
"application/json",
strings.NewReader(jsonData),
)
if err != nil {
fmt.Println("Error:", err)
return
}
defer resp.Body.Close()
fmt.Println("POST Status:", resp.Status)
}
Output:
GET Response:
{"userId":1,"id":1,"title":"sunt aut facere...","body":"quia et suscipit..."}
POST Status: 201 Created
🔹 HTTP Client with Custom Configuration
Create custom HTTP clients with timeouts and headers:
package main
import (
"fmt"
"io"
"net/http"
"time"
)
func main() {
// Custom HTTP client
client := &http.Client{
Timeout: 10 * time.Second,
}
// Create request with custom headers
req, err := http.NewRequest("GET", "https://api.github.com/users/golang", nil)
if err != nil {
fmt.Println("Error:", err)
return
}
req.Header.Set("User-Agent", "Go-HTTP-Client/1.0")
req.Header.Set("Accept", "application/json")
// Send request
resp, err := client.Do(req)
if err != nil {
fmt.Println("Error:", err)
return
}
defer resp.Body.Close()
fmt.Println("Status:", resp.Status)
fmt.Println("Headers:", resp.Header.Get("Content-Type"))
body, _ := io.ReadAll(resp.Body)
fmt.Println("Response length:", len(body), "bytes")
}
Output:
Status: 200 OK
Headers: application/json; charset=utf-8
Response length: 1234 bytes
🔹 REST API Example
Build a simple REST API with CRUD operations:
package main
import (
"encoding/json"
"fmt"
"net/http"
"strconv"
"strings"
)
type Task struct {
ID int `json:"id"`
Name string `json:"name"`
Done bool `json:"done"`
}
var tasks = []Task{
{ID: 1, Name: "Learn Go", Done: false},
{ID: 2, Name: "Build API", Done: true},
}
func tasksHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
switch r.Method {
case "GET":
json.NewEncoder(w).Encode(tasks)
case "POST":
var newTask Task
json.NewDecoder(r.Body).Decode(&newTask)
newTask.ID = len(tasks) + 1
tasks = append(tasks, newTask)
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(newTask)
default:
w.WriteHeader(http.StatusMethodNotAllowed)
}
}
func taskHandler(w http.ResponseWriter, r *http.Request) {
idStr := strings.TrimPrefix(r.URL.Path, "/tasks/")
id, _ := strconv.Atoi(idStr)
for i, task := range tasks {
if task.ID == id {
if r.Method == "DELETE" {
tasks = append(tasks[:i], tasks[i+1:]...)
w.WriteHeader(http.StatusNoContent)
return
}
}
}
w.WriteHeader(http.StatusNotFound)
}
func main() {
http.HandleFunc("/tasks", tasksHandler)
http.HandleFunc("/tasks/", taskHandler)
fmt.Println("REST API server running on :8080")
http.ListenAndServe(":8080", nil)
}
Output:
REST API server running on :8080
GET /tasks → List all tasks
POST /tasks → Create new task
DELETE /tasks/1 → Delete task with ID 1