second commit
This commit is contained in:
parent
2aed21477f
commit
5f75ebb02c
|
@ -1,9 +1,11 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
_ "awesomeProject/internal/store"
|
||||
"awesomeProject/server"
|
||||
"awesomeProject/store/factory"
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
|
@ -11,6 +13,38 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
func sendOddNum(cn chan<- int) {
|
||||
number := 1
|
||||
for {
|
||||
cn <- number
|
||||
number += 2 // 生成下一个奇数
|
||||
fmt.Println("inside:", number)
|
||||
time.Sleep(1 * time.Second) // 每 1 秒发送一次
|
||||
}
|
||||
}
|
||||
|
||||
func sendEvenNum(cn chan<- int) {
|
||||
number := 2
|
||||
for {
|
||||
cn <- number
|
||||
number += 2
|
||||
fmt.Println("inside:", number)
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
//func main() {
|
||||
// cn := make(chan int, 10)
|
||||
// go sendOddNum(cn)
|
||||
// go sendEvenNum(cn)
|
||||
//
|
||||
// for {
|
||||
// num := <-cn
|
||||
// time.Sleep(5 * time.Second)
|
||||
// fmt.Println("Received:", num)
|
||||
// }
|
||||
//}
|
||||
|
||||
func main() {
|
||||
s, err := factory.New("mem") // 创建图书数据存储模块实例
|
||||
if err != nil {
|
||||
|
|
4
go.mod
4
go.mod
|
@ -1 +1,5 @@
|
|||
module awesomeProject
|
||||
|
||||
go 1.23.2
|
||||
|
||||
require github.com/gorilla/mux v1.8.1
|
||||
|
|
|
@ -1 +1,63 @@
|
|||
package store
|
||||
|
||||
import (
|
||||
mystore "awesomeProject/store"
|
||||
factory "awesomeProject/store/factory"
|
||||
"errors"
|
||||
"sync"
|
||||
)
|
||||
|
||||
func init() {
|
||||
factory.Register("mem", &MemStore{
|
||||
books: make(map[string]*mystore.Book),
|
||||
})
|
||||
}
|
||||
|
||||
type MemStore struct {
|
||||
sync.RWMutex
|
||||
books map[string]*mystore.Book
|
||||
}
|
||||
|
||||
func (m *MemStore) Create(book *mystore.Book) error {
|
||||
if _, ok := m.books[book.Id]; ok {
|
||||
return errors.New("book is existed")
|
||||
}
|
||||
m.books[book.Id] = book
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MemStore) Update(book *mystore.Book) error {
|
||||
oldBook, ok := m.books[book.Id]
|
||||
if !ok {
|
||||
return errors.New("book not found")
|
||||
}
|
||||
oldBook.Name = book.Name
|
||||
oldBook.Authors = book.Authors
|
||||
oldBook.Press = book.Press
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MemStore) Get(s string) (mystore.Book, error) {
|
||||
oldBook, ok := m.books[s]
|
||||
if !ok {
|
||||
return mystore.Book{}, errors.New("book not found")
|
||||
} else {
|
||||
return *oldBook, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MemStore) GetAll() ([]mystore.Book, error) {
|
||||
books := make([]mystore.Book, 0, len(m.books)) // 初始化切片,预分配容量
|
||||
for _, book := range m.books {
|
||||
books = append(books, *book) // 解引用并添加到切片中
|
||||
}
|
||||
return books, nil // 返回所有书籍
|
||||
}
|
||||
|
||||
func (m *MemStore) Delete(s string) error {
|
||||
if _, ok := m.books[s]; !ok {
|
||||
return errors.New("book not found") // 如果书籍未找到,返回错误
|
||||
}
|
||||
delete(m.books, s) // 从 map 中删除书籍
|
||||
return nil // 删除成功,返回 nil
|
||||
}
|
||||
|
|
|
@ -1 +1,30 @@
|
|||
package middleware
|
||||
|
||||
import (
|
||||
"log"
|
||||
"mime"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func Logging(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
log.Printf("recv a %s request from %s", req.Method, req.RemoteAddr)
|
||||
next.ServeHTTP(w, req)
|
||||
})
|
||||
}
|
||||
|
||||
func Validating(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
contentType := req.Header.Get("Content-Type")
|
||||
mediatype, _, err := mime.ParseMediaType(contentType)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if mediatype != "application/json" {
|
||||
http.Error(w, "invalid Content-Type", http.StatusUnsupportedMediaType)
|
||||
return
|
||||
}
|
||||
next.ServeHTTP(w, req)
|
||||
})
|
||||
}
|
||||
|
|
120
server/server.go
120
server/server.go
|
@ -1 +1,121 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"awesomeProject/server/middleware"
|
||||
"awesomeProject/store"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/gorilla/mux"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
type BookStoreServer struct {
|
||||
s store.Store
|
||||
srv *http.Server
|
||||
}
|
||||
|
||||
func NewBookStoreServer(addr string, s store.Store) *BookStoreServer {
|
||||
srv := &BookStoreServer{s: s, srv: &http.Server{Addr: addr}}
|
||||
router := mux.NewRouter()
|
||||
router.HandleFunc("/book", srv.createBookHandler).Methods("POST")
|
||||
router.HandleFunc("/book/{id}", srv.updateBookHandler).Methods("POST")
|
||||
router.HandleFunc("/book/{id}", srv.getBookHandler).Methods("GET")
|
||||
router.HandleFunc("/book", srv.getAllBooksHandler).Methods("GET")
|
||||
router.HandleFunc("/book/{id}", srv.delBookHandler).Methods("DELETE")
|
||||
srv.srv.Handler = middleware.Logging(middleware.Validating(router))
|
||||
return srv
|
||||
}
|
||||
|
||||
func (bs *BookStoreServer) Shutdown(ctx context.Context) error {
|
||||
return bs.srv.Shutdown(ctx)
|
||||
}
|
||||
|
||||
func (bs *BookStoreServer) createBookHandler(w http.ResponseWriter, req *http.Request) {
|
||||
dec := json.NewDecoder(req.Body)
|
||||
var book store.Book
|
||||
if err := dec.Decode(&book); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if err := bs.s.Create(&book); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (bs *BookStoreServer) updateBookHandler(w http.ResponseWriter, req *http.Request) {
|
||||
dec := json.NewDecoder(req.Body)
|
||||
var book store.Book
|
||||
if err := dec.Decode(&book); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if err := bs.s.Update(&book); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (bs *BookStoreServer) getAllBooksHandler(w http.ResponseWriter, req *http.Request) {
|
||||
books, err := bs.s.GetAll()
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
response(w, books)
|
||||
}
|
||||
|
||||
func (bs *BookStoreServer) getBookHandler(w http.ResponseWriter, req *http.Request) {
|
||||
id, ok := mux.Vars(req)["id"]
|
||||
if !ok {
|
||||
http.Error(w, "no id found in request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
err := bs.s.Delete(id)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (bs *BookStoreServer) delBookHandler(w http.ResponseWriter, req *http.Request) {
|
||||
id, ok := mux.Vars(req)["id"]
|
||||
if !ok {
|
||||
http.Error(w, "no id found in request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
book, err := bs.s.Get(id)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
response(w, book)
|
||||
}
|
||||
|
||||
func response(w http.ResponseWriter, v interface{}) {
|
||||
data, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if _, err := w.Write(data); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
func (bs *BookStoreServer) ListenAndServe() (<-chan error, error) {
|
||||
var err error
|
||||
errChan := make(chan error)
|
||||
go func() {
|
||||
err = bs.srv.ListenAndServe()
|
||||
errChan <- err
|
||||
}()
|
||||
select {
|
||||
case err = <-errChan:
|
||||
return nil, err
|
||||
case <-time.After(time.Second):
|
||||
return errChan, nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ func Register(name string, p store.Store) {
|
|||
}
|
||||
providers[name] = p
|
||||
}
|
||||
|
||||
func New(providerName string) (store.Store, error) {
|
||||
providersMu.RLock()
|
||||
p, ok := providers[providerName]
|
||||
|
|
Loading…
Reference in New Issue