Go - 单机版缓存实现

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}

你可能感兴趣的:(go缓存)