Go Web Server Example
This snippet shows a simple REST API server in Go with middleware.
GO
1
2 package main
3
4 import (
5 "context"
6 "encoding/json"
7 "fmt"
8 "log"
9 "net/http"
10 "strconv"
11 "time"
12
13 "github.com/gorilla/mux"
14 )
15
16 type User struct {
17 ID int `json:"id"`
18 Name string `json:"name"`
19 Email string `json:"email"`
20 }
21
22 type Server struct {
23 router *mux.Router
24 users []User
25 }
26
27 func NewServer() *Server {
28 s := &Server{
29 router: mux.NewRouter(),
30 users: []User{
31 {ID: 1, Name: "John Doe", Email: "john@example.com"},
32 {ID: 2, Name: "Jane Smith", Email: "jane@example.com"},
33 },
34 }
35 s.setupRoutes()
36 return s
37 }
38
39 func (s *Server) setupRoutes() {
40 // Middleware
41 s.router.Use(s.loggingMiddleware)
42 s.router.Use(s.corsMiddleware)
43
44 // Routes
45 s.router.HandleFunc("/api/users", s.getUsers).Methods("GET")
46 s.router.HandleFunc("/api/users/{id}", s.getUser).Methods("GET")
47 s.router.HandleFunc("/api/users", s.createUser).Methods("POST")
48 s.router.HandleFunc("/api/users/{id}", s.updateUser).Methods("PUT")
49 s.router.HandleFunc("/api/users/{id}", s.deleteUser).Methods("DELETE")
50 }
51
52 func (s *Server) loggingMiddleware(next http.Handler) http.Handler {
53 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
54 start := time.Now()
55 next.ServeHTTP(w, r)
56 log.Printf(
57 "%s %s %s %v",
58 r.Method,
59 r.RequestURI,
60 r.RemoteAddr,
61 time.Since(start),
62 )
63 })
64 }
65
66 func (s *Server) corsMiddleware(next http.Handler) http.Handler {
67 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
68 w.Header().Set("Access-Control-Allow-Origin", "*")
69 w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
70 w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
71
72 if r.Method == "OPTIONS" {
73 w.WriteHeader(http.StatusOK)
74 return
75 }
76
77 next.ServeHTTP(w, r)
78 })
79 }
80
81 func (s *Server) getUsers(w http.ResponseWriter, r *http.Request) {
82 w.Header().Set("Content-Type", "application/json")
83 json.NewEncoder(w).Encode(s.users)
84 }
85
86 func (s *Server) getUser(w http.ResponseWriter, r *http.Request) {
87 vars := mux.Vars(r)
88 id, _ := strconv.Atoi(vars["id"])
89
90 for _, user := range s.users {
91 if user.ID == id {
92 w.Header().Set("Content-Type", "application/json")
93 json.NewEncoder(w).Encode(user)
94 return
95 }
96 }
97
98 http.NotFound(w, r)
99 }
100
101 func (s *Server) createUser(w http.ResponseWriter, r *http.Request) {
102 var user User
103 if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
104 http.Error(w, err.Error(), http.StatusBadRequest)
105 return
106 }
107
108 user.ID = len(s.users) + 1
109 s.users = append(s.users, user)
110
111 w.Header().Set("Content-Type", "application/json")
112 w.WriteHeader(http.StatusCreated)
113 json.NewEncoder(w).Encode(user)
114 }
115
116 func (s *Server) updateUser(w http.ResponseWriter, r *http.Request) {
117 vars := mux.Vars(r)
118 id, _ := strconv.Atoi(vars["id"])
119
120 var updatedUser User
121 if err := json.NewDecoder(r.Body).Decode(&updatedUser); err != nil {
122 http.Error(w, err.Error(), http.StatusBadRequest)
123 return
124 }
125
126 for i, user := range s.users {
127 if user.ID == id {
128 updatedUser.ID = id
129 s.users[i] = updatedUser
130 w.Header().Set("Content-Type", "application/json")
131 json.NewEncoder(w).Encode(updatedUser)
132 return
133 }
134 }
135
136 http.NotFound(w, r)
137 }
138
139 func (s *Server) deleteUser(w http.ResponseWriter, r *http.Request) {
140 vars := mux.Vars(r)
141 id, _ := strconv.Atoi(vars["id"])
142
143 for i, user := range s.users {
144 if user.ID == id {
145 s.users = append(s.users[:i], s.users[i+1:]...)
146 w.WriteHeader(http.StatusNoContent)
147 return
148 }
149 }
150
151 http.NotFound(w, r)
152 }
153
154 func main() {
155 server := NewServer()
156
157 fmt.Println("Server starting on port 8080...")
158 log.Fatal(http.ListenAndServe(":8080", server.router))
159 }