Go HTTP 서버
Go 표준 라이브러리로 만드는 HTTP REST 서버. 뮤텍스 기반 인메모리 스토어, JSON 응답 헬퍼 포함.
package main
import (
"encoding/json"
"log"
"net/http"
"os"
"strconv"
"sync"
"time"
)
type Task struct {
ID int `json:"id"`
Title string `json:"title"`
Done bool `json:"done"`
CreatedAt time.Time `json:"createdAt"`
}
type Store struct {
mu sync.RWMutex
tasks map[int]Task
nextID int
}
func NewStore() *Store { return &Store{tasks: make(map[int]Task), nextID: 1} }
func (s *Store) All() []Task {
s.mu.RLock()
defer s.mu.RUnlock()
out := make([]Task, 0, len(s.tasks))
for _, t := range s.tasks { out = append(out, t) }
return out
}
func (s *Store) Get(id int) (Task, bool) {
s.mu.RLock()
defer s.mu.RUnlock()
t, ok := s.tasks[id]
return t, ok
}
func (s *Store) Create(title string) Task {
s.mu.Lock()
defer s.mu.Unlock()
t := Task{ID: s.nextID, Title: title, CreatedAt: time.Now()}
s.tasks[s.nextID] = t
s.nextID++
return t
}
func (s *Store) Delete(id int) bool {
s.mu.Lock()
defer s.mu.Unlock()
if _, ok := s.tasks[id]; !ok { return false }
delete(s.tasks, id)
return true
}
func writeJSON(w http.ResponseWriter, code int, v any) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(code)
json.NewEncoder(w).Encode(v)
}
func writeError(w http.ResponseWriter, code int, msg string) {
writeJSON(w, code, map[string]string{"error": msg})
}
func main() {
store := NewStore()
mux := http.NewServeMux()
mux.HandleFunc("GET /tasks", func(w http.ResponseWriter, _ *http.Request) {
writeJSON(w, http.StatusOK, store.All())
})
mux.HandleFunc("POST /tasks", func(w http.ResponseWriter, r *http.Request) {
var body struct{ Title string `json:"title"` }
if err := json.NewDecoder(r.Body).Decode(&body); err != nil || body.Title == "" {
writeError(w, http.StatusBadRequest, "title is required")
return
}
writeJSON(w, http.StatusCreated, store.Create(body.Title))
})
mux.HandleFunc("GET /tasks/{id}", func(w http.ResponseWriter, r *http.Request) {
id, _ := strconv.Atoi(r.PathValue("id"))
t, ok := store.Get(id)
if !ok { writeError(w, http.StatusNotFound, "not found"); return }
writeJSON(w, http.StatusOK, t)
})
mux.HandleFunc("DELETE /tasks/{id}", func(w http.ResponseWriter, r *http.Request) {
id, _ := strconv.Atoi(r.PathValue("id"))
if !store.Delete(id) { writeError(w, http.StatusNotFound, "not found"); return }
w.WriteHeader(http.StatusNoContent)
})
port := os.Getenv("PORT")
if port == "" { port = "8080" }
log.Printf("Listening on :%s", port)
log.Fatal(http.ListenAndServe(":"+port, mux))
}