关于go:Go-单机版缓存实现

0次阅读

共计 3339 个字符,预计需要花费 9 分钟才能阅读完成。

Go – 单机版缓存

工程目录树

$ tree cache-server
cache-server
├── caches
│   └── cache.go
├── go.mod
├── go.sum
├── main.go
├── servers
│   ├── http.go
│   └── IServer.go
└── utils
    └── byte.go

utils

// byte.go
package utils


func Copy(src []byte) []byte{dst := make([]byte, len(src))
    copy(dst, src)
    return dst
}

caches

// 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
    
}

servers

// 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

// 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}
正文完
 0