$ tree cache-server
cache-server
├── caches
│ └── cache.go
├── go.mod
├── go.sum
├── main.go
├── servers
│ ├── http.go
│ └── IServer.go
└── utils
└── byte.go
// byte.go
package utils
func Copy(src []byte) []byte{dst := make([]byte, len(src))
copy(dst, src)
return dst
}
// cache.go
package caches
import(
"sync"
"cache-server/utils"
)
// cache data struct
type Cache struct{data map[string][]byte
count int64
lock *sync.RWMutex
}
func Newcache() *Cache{
return &Cache{data: make(map[string][]byte, 256),
count:0,
lock: &sync.RWMutex{},}
}
// cache's crud methods
// create method & update method
func (c *Cache) Set(k string, v []byte){c.lock.Lock()
_, ok := c.data[k]
if !ok {// c.data[k] = v
c.count++
}
c.data[k] = utils.Copy(v)
c.lock.Unlock()}
// read method
func (c *Cache) Get(k string) ([]byte, bool){c.lock.RLock()
defer c.lock.RUnlock()
v, ok := c.data[k]
return v,ok
}
// delete method
func (c *Cache) Delete(k string){c.lock.Lock()
_, ok := c.data[k]
if ok {delete(c.data, k)
c.count--
}
c.lock.Unlock()}
// count method
func (c *Cache) Count() int64 {c.lock.RLock()
defer c.lock.RUnlock()
return c.count
}
// IServer.go
package servers
type Server interface{Run(ipAddress string)error
}
// http.go
package servers
import(
"net/http"
"encoding/json"
"io/ioutil"
"cache-server/caches"
"github.com/julienschmidt/httprouter"
)
type HttpServer struct {cache *caches.Cache}
// 返回一个对于 cache 的新 HTTP 服务器
func NewHttpServer(cache *caches.Cache) *HttpServer{
return &HttpServer{cache: cache,}
}
func (this *HttpServer) Run(ipAddress string) error{return http.ListenAndServe(ipAddress, this.routerHandler())
}
// register routers
func (this *HttpServer) routerHandler() http.Handler{
// github.com/julienschmidt/httprouter
r := httprouter.New()
// get cache by key
r.GET("/cache/:key", this.getHandler)
// set cache by key
r.PUT("/cache/:key", this.setHandler)
// delete cache by key
r.DELETE("/cache/:key", this.deleteHandler)
// get cache's data count
r.GET("/counts", this.countHandler)
return r
}
func (this *HttpServer) getHandler(w http.ResponseWriter, r *http.Request, params httprouter.Params) {key := params.ByName("key")
value, ok := this.cache.Get(key)
if ok {w.Write(value)
}else{w.WriteHeader(http.StatusNotFound)
return
}
}
func (this *HttpServer) setHandler(w http.ResponseWriter, r *http.Request, params httprouter.Params) {key := params.ByName("key")
value, err := ioutil.ReadAll(r.Body)
if err != nil {w.WriteHeader(http.StatusInternalServerError)
return
}
this.cache.Set(key, value)
w.Write([]byte("set success"))
}
func (this *HttpServer) deleteHandler(w http.ResponseWriter, r *http.Request, params httprouter.Params) {key := params.ByName("key")
_, ok := this.cache.Get(key)
if !ok {w.WriteHeader(http.StatusNotFound)
}
this.cache.Delete(key)
}
func (this *HttpServer) countHandler(w http.ResponseWriter, r *http.Request, params httprouter.Params) {counts, err := json.Marshal(map[string]interface{}{"count": this.cache.Count()})
if err != nil{w.WriteHeader(http.StatusInternalServerError)
return
}
w.Write(counts)
}
// main.go
package main
import(
"cache-server/caches"
"cache-server/servers"
)
func main(){c := caches.Newcache()
err := servers.NewHttpServer(c).Run(":8080")
if err != nil {panic(err)
}
}
$ cd ./cache-server && go mod init cache-server
$ go get github.com/julienschmidt/httprouter
$ go run main.go
$ curl http://127.0.0.1:8080/cache/k
$ curl http://127.0.0.1:8080/cache/k -X PUT -d 'v'
set success%
$ curl http://127.0.0.1:8080/cache/k
v%
$ curl http://127.0.0.1:8080/cache/k -X DELETE
$ curl http://127.0.0.1:8080/cache/k
$ curl http://127.0.0.1:8080/counts
{"count":0}%
$ curl http://127.0.0.1:8080/cache/k -X PUT -d 'v'
set success%
$ curl http://127.0.0.1:8080/counts
{"count":1}