Bookmarks API

REST handlers for bookmarks with JSON helpers.

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"log/slog"
	"net/http"
	"time"
)

type Bookmark struct {
	ID    string `json:"id"`
	URL   string `json:"url"`
	Title string `json:"title"`
}

var bookmarks = []Bookmark{
	{ID: "1", URL: "https://go.dev", Title: "Go"},
	{ID: "2", URL: "https://pkg.go.dev", Title: "Go Packages"},
}

func writeJSON(w http.ResponseWriter, status int, data any) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(status)
	json.NewEncoder(w).Encode(data)
}

func writeError(w http.ResponseWriter, status int, message string) {
	writeJSON(w, status, map[string]string{"error": message})
}

func listBookmarks(w http.ResponseWriter, r *http.Request) {
	writeJSON(w, http.StatusOK, bookmarks)
}

func getBookmark(w http.ResponseWriter, r *http.Request) {
	id := r.PathValue("id")
	for _, b := range bookmarks {
		if b.ID == id {
			writeJSON(w, http.StatusOK, b)
			return
		}
	}
	writeError(w, http.StatusNotFound, "bookmark not found")
}

func createBookmark(w http.ResponseWriter, r *http.Request) {
	var input struct {
		URL   string `json:"url"`
		Title string `json:"title"`
	}
	if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
		writeError(w, http.StatusBadRequest, "invalid JSON")
		return
	}
	if input.URL == "" {
		writeError(w, http.StatusBadRequest, "url is required")
		return
	}

	b := Bookmark{
		ID:    fmt.Sprintf("%d", time.Now().UnixNano()),
		URL:   input.URL,
		Title: input.Title,
	}
	bookmarks = append(bookmarks, b)
	slog.Info("bookmark created", "id", b.ID, "url", b.URL)
	writeJSON(w, http.StatusCreated, b)
}

func main() {
	mux := http.NewServeMux()
	mux.HandleFunc("GET /bookmarks", listBookmarks)
	mux.HandleFunc("GET /bookmarks/{id}", getBookmark)
	mux.HandleFunc("POST /bookmarks", createBookmark)

	slog.Info("listening", "addr", ":8080")
	log.Fatal(http.ListenAndServe(":8080", mux))
}

💻 Run locally

Copy the code above and run it on your machine

© 2026 ByteLearn.dev. Free courses for developers. · Privacy