Package http provides HTTP client and server implementations. Get, Head, Post, and PostForm make HTTP requests. The Client type supports custom configurations. The Server type provides an HTTP server.
HTTP Client
Making Requests
Get
func Get(url string) (resp *Response, err error)
Issues a GET request to the specified URL. Returns the response and any error encountered.resp, err := http.Get("https://api.example.com/data")
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
Post
func Post(url, contentType string, body io.Reader) (resp *Response, err error)
Issues a POST request to the specified URL.data := strings.NewReader(`{"name":"John"}`)
resp, err := http.Post("https://api.example.com/users",
"application/json", data)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
PostForm
func PostForm(url string, data url.Values) (resp *Response, err error)
Issues a POST request with form data.data := url.Values{}
data.Set("username", "john")
data.Set("password", "secret")
resp, err := http.PostForm("https://example.com/login", data)
Head
func Head(url string) (resp *Response, err error)
Issues a HEAD request to the specified URL.resp, err := http.Head("https://example.com")
if err != nil {
log.Fatal(err)
}
fmt.Println("Status:", resp.Status)
fmt.Println("Content-Length:", resp.ContentLength)
Client Type
An HTTP client. The zero value (DefaultClient) is a usable client that uses DefaultTransport. Clients are safe for concurrent use by multiple goroutines.type Client struct {
Transport RoundTripper
CheckRedirect func(req *Request, via []*Request) error
Jar CookieJar
Timeout time.Duration
}
Custom client with timeout:client := &http.Client{
Timeout: 10 * time.Second,
}
resp, err := client.Get("https://api.example.com")
Client.Do
func (c *Client) Do(req *Request) (*Response, error)
Sends an HTTP request and returns an HTTP response.req, _ := http.NewRequest("GET", "https://api.example.com", nil)
req.Header.Add("Authorization", "Bearer token123")
client := &http.Client{}
resp, err := client.Do(req)
Request Type
NewRequest
func NewRequest(method, url string, body io.Reader) (*Request, error)
Returns a new Request given a method, URL, and optional body.// GET request
req, err := http.NewRequest("GET", "https://api.example.com/users", nil)
// POST request with body
data := strings.NewReader(`{"name":"Alice"}`)
req, err := http.NewRequest("POST", "https://api.example.com/users", data)
req.Header.Set("Content-Type", "application/json")
NewRequestWithContext
func NewRequestWithContext(ctx context.Context, method, url string, body io.Reader) (*Request, error)
Like NewRequest but includes a context for cancellation and timeouts.ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
Represents an HTTP request received by a server or to be sent by a client.type Request struct {
Method string
URL *url.URL
Header Header
Body io.ReadCloser
// ... more fields
}
Response Type
Represents the response from an HTTP request.type Response struct {
Status string // e.g. "200 OK"
StatusCode int // e.g. 200
Header Header
Body io.ReadCloser
// ... more fields
}
Always close the response body:resp, err := http.Get(url)
if err != nil {
return err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
HTTP Server
Creating a Server
ListenAndServe
func ListenAndServe(addr string, handler Handler) error
Listens on the TCP network address and serves HTTP requests.http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!")
})
log.Fatal(http.ListenAndServe(":8080", nil))
ListenAndServeTLS
func ListenAndServeTLS(addr, certFile, keyFile string, handler Handler) error
Like ListenAndServe but for HTTPS.log.Fatal(http.ListenAndServeTLS(":443", "cert.pem", "key.pem", nil))
Defines parameters for running an HTTP server.type Server struct {
Addr string
Handler Handler
ReadTimeout time.Duration
WriteTimeout time.Duration
// ... more fields
}
Custom server:server := &http.Server{
Addr: ":8080",
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
MaxHeaderBytes: 1 << 20,
}
log.Fatal(server.ListenAndServe())
Handler Interface
Objects that can serve HTTP requests.type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
Custom handler:type MyHandler struct{}
func (h *MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello from custom handler"))
}
http.ListenAndServe(":8080", &MyHandler{})
An adapter to allow use of ordinary functions as HTTP handlers.type HandlerFunc func(ResponseWriter, *Request)
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
HandleFunc
func HandleFunc(pattern string, handler func(ResponseWriter, *Request))
Registers the handler function for the given pattern in the DefaultServeMux.http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, %s!", r.URL.Query().Get("name"))
})
http.HandleFunc("/api/users", handleUsers)
Handle
func Handle(pattern string, handler Handler)
Registers the handler for the given pattern in the DefaultServeMux.
Request Handling
Used by an HTTP handler to construct an HTTP response.type ResponseWriter interface {
Header() Header
Write([]byte) (int, error)
WriteHeader(statusCode int)
}
Usage:func handler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write([]byte(`{"status":"ok"}`))
}
Status Codes
const (
StatusOK = 200
StatusCreated = 201
StatusAccepted = 202
StatusNoContent = 204
StatusMovedPermanently = 301
StatusFound = 302
StatusBadRequest = 400
StatusUnauthorized = 401
StatusForbidden = 403
StatusNotFound = 404
StatusMethodNotAllowed = 405
StatusInternalServerError = 500
StatusServiceUnavailable = 503
)
Cookies
SetCookie
func SetCookie(w ResponseWriter, cookie *Cookie)
Adds a Set-Cookie header to the ResponseWriter’s headers.cookie := &http.Cookie{
Name: "session",
Value: "abc123",
Path: "/",
MaxAge: 3600,
HttpOnly: true,
Secure: true,
}
http.SetCookie(w, cookie)
Request.Cookie
func (r *Request) Cookie(name string) (*Cookie, error)
Returns the named cookie from the request.cookie, err := r.Cookie("session")
if err == nil {
fmt.Println("Session:", cookie.Value)
}
File Server
FileServer
func FileServer(root FileSystem) Handler
Returns a handler that serves HTTP requests with the contents of the file system rooted at root.// Serve static files from ./static directory
fs := http.FileServer(http.Dir("./static"))
http.Handle("/static/", http.StripPrefix("/static/", fs))
ServeFile
func ServeFile(w ResponseWriter, r *Request, name string)
Replies to the request with the contents of the named file or directory.http.HandleFunc("/download", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "./files/document.pdf")
})
Examples
Simple HTTP GET
package main
import (
"fmt"
"io"
"log"
"net/http"
)
func main() {
resp, err := http.Get("https://api.github.com")
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
fmt.Println("Status:", resp.Status)
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}
POST Request with JSON
package main
import (
"bytes"
"encoding/json"
"fmt"
"log"
"net/http"
)
type User struct {
Name string `json:"name"`
Email string `json:"email"`
}
func main() {
user := User{Name: "Alice", Email: "[email protected]"}
jsonData, _ := json.Marshal(user)
resp, err := http.Post("https://api.example.com/users",
"application/json", bytes.NewBuffer(jsonData))
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
fmt.Println("Status:", resp.StatusCode)
}
Custom Client with Timeout
package main
import (
"context"
"fmt"
"log"
"net/http"
"time"
)
func main() {
client := &http.Client{
Timeout: 5 * time.Second,
}
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
req, _ := http.NewRequestWithContext(ctx, "GET",
"https://api.example.com/slow", nil)
req.Header.Set("Authorization", "Bearer token123")
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
fmt.Println("Status:", resp.Status)
}
Simple HTTP Server
package main
import (
"fmt"
"log"
"net/http"
)
func main() {
// Handle root path
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Welcome to the home page!")
})
// Handle /hello path
http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
name := r.URL.Query().Get("name")
if name == "" {
name = "Guest"
}
fmt.Fprintf(w, "Hello, %s!", name)
})
// Handle /api/status path
http.HandleFunc("/api/status", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, `{"status":"healthy","version":"1.0"}`)
})
fmt.Println("Server starting on :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
REST API Server
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
)
type User struct {
ID int `json:"id"`
Name string `json:"name"`
}
var users = []User{
{ID: 1, Name: "Alice"},
{ID: 2, Name: "Bob"},
}
func getUsers(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(users)
}
func createUser(w http.ResponseWriter, r *http.Request) {
var user User
if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
user.ID = len(users) + 1
users = append(users, user)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(user)
}
func main() {
http.HandleFunc("/api/users", func(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "GET":
getUsers(w, r)
case "POST":
createUser(w, r)
default:
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
}
})
fmt.Println("API server running on :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}