second commit
This commit is contained in:
parent
2aed21477f
commit
5f75ebb02c
|
@ -1,9 +1,11 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
_ "awesomeProject/internal/store"
|
||||||
"awesomeProject/server"
|
"awesomeProject/server"
|
||||||
"awesomeProject/store/factory"
|
"awesomeProject/store/factory"
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
@ -11,6 +13,38 @@ import (
|
||||||
"time"
|
"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() {
|
func main() {
|
||||||
s, err := factory.New("mem") // 创建图书数据存储模块实例
|
s, err := factory.New("mem") // 创建图书数据存储模块实例
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
4
go.mod
4
go.mod
|
@ -1 +1,5 @@
|
||||||
module awesomeProject
|
module awesomeProject
|
||||||
|
|
||||||
|
go 1.23.2
|
||||||
|
|
||||||
|
require github.com/gorilla/mux v1.8.1
|
||||||
|
|
|
@ -1 +1,63 @@
|
||||||
package store
|
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
|
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
|
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
|
providers[name] = p
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(providerName string) (store.Store, error) {
|
func New(providerName string) (store.Store, error) {
|
||||||
providersMu.RLock()
|
providersMu.RLock()
|
||||||
p, ok := providers[providerName]
|
p, ok := providers[providerName]
|
||||||
|
|
Loading…
Reference in New Issue