Go语言Tips
时间日期格式化
time.Now().Format("2006-01-02")
原生DefaultServeMux支持restful路由
ref: https://towardsdev.com/how-to-create-rest-api-in-golang-6448d1de294c
package main
import (
"encoding/json"
"net/http"
"regexp"
"sync"
)
var (
listUserRe = regexp.MustCompile(`^\/users[\/]*$`)
getUserRe = regexp.MustCompile(`^\/users\/(\d+)$`)
createUserRe = regexp.MustCompile(`^\/users[\/]*$`)
)
type user struct {
ID string `json:"id"`
Name string `json:"name"`
}
type datastore struct {
m map[string]user
*sync.RWMutex
}
type userHandler struct {
store *datastore
}
func (h *userHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Header().Set("content-type", "application/json")
switch {
case r.Method == http.MethodGet && listUserRe.MatchString(r.URL.Path):
h.List(w, r)
return
case r.Method == http.MethodGet && getUserRe.MatchString(r.URL.Path):
h.Get(w, r)
return
case r.Method == http.MethodPost && createUserRe.MatchString(r.URL.Path):
h.Create(w, r)
return
default:
notFound(w, r)
return
}
}
func (h *userHandler) List(w http.ResponseWriter, r *http.Request) {
h.store.RLock()
users := make([]user, 0, len(h.store.m))
for _, v := range h.store.m {
users = append(users, v)
}
h.store.RUnlock()
jsonBytes, err := json.Marshal(users)
if err != nil {
internalServerError(w, r)
return
}
w.WriteHeader(http.StatusOK)
w.Write(jsonBytes)
}
func (h *userHandler) Get(w http.ResponseWriter, r *http.Request) {
matches := getUserRe.FindStringSubmatch(r.URL.Path)
if len(matches) < 2 {
notFound(w, r)
return
}
h.store.RLock()
u, ok := h.store.m[matches[1]]
h.store.RUnlock()
if !ok {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("user not found"))
return
}
jsonBytes, err := json.Marshal(u)
if err != nil {
internalServerError(w, r)
return
}
w.WriteHeader(http.StatusOK)
w.Write(jsonBytes)
}
func (h *userHandler) Create(w http.ResponseWriter, r *http.Request) {
var u user
if err := json.NewDecoder(r.Body).Decode(&u); err != nil {
internalServerError(w, r)
return
}
h.store.Lock()
h.store.m[u.ID] = u
h.store.Unlock()
jsonBytes, err := json.Marshal(u)
if err != nil {
internalServerError(w, r)
return
}
w.WriteHeader(http.StatusOK)
w.Write(jsonBytes)
}
func internalServerError(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("internal server error"))
}
func notFound(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotFound)
w.Write([]byte("not found"))
}
func main() {
mux := http.NewServeMux()
userH := &userHandler{
store: &datastore{
m: map[string]user{
"1": user{ID: "1", Name: "bob"},
},
RWMutex: &sync.RWMutex{},
},
}
mux.Handle("/users", userH)
mux.Handle("/users/", userH)
http.ListenAndServe("localhost:8080", mux)
}