Go - 单机版缓存
工程目录树
$ tree cache-servercache-server├── caches│ └── cache.go├── go.mod├── go.sum├── main.go├── servers│ ├── http.go│ └── IServer.go└── utils └── byte.go
utils
// byte.gopackage utilsfunc Copy(src []byte) []byte{ dst := make([]byte, len(src)) copy(dst, src) return dst}
caches
// cache.gopackage cachesimport( "sync" "cache-server/utils")// cache data structtype 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 methodfunc (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 methodfunc (c *Cache) Get(k string) ([]byte, bool){ c.lock.RLock() defer c.lock.RUnlock() v, ok := c.data[k] return v,ok}// delete methodfunc (c *Cache) Delete(k string){ c.lock.Lock() _, ok := c.data[k] if ok { delete(c.data, k) c.count-- } c.lock.Unlock()}// count methodfunc (c *Cache) Count() int64 { c.lock.RLock() defer c.lock.RUnlock() return c.count }
servers
// IServer.gopackage serverstype Server interface{ Run(ipAddress string)error}
// http.gopackage serversimport( "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 routersfunc (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
// main.gopackage mainimport( "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}