golang并发
先贴代码
package cache
import (
"fmt"
)
type entry struct {
res result
ready chan struct{} //closed when res is ready
}
type request struct {
key string
response chan<- result
}
type Memo struct {
requests chan request
}
type Func func(key string) (interface{}, error)
type result struct {
value interface{}
err error
}
func New(f Func) *Memo {
memo := &Memo{requests: make(chan request)}
go memo.server(f)
return memo
}
func (memo *Memo) Get(key string) (value interface{}, err error) {
response := make(chan result)
memo.requests <- request{key, response}
res := <-response
return res.value, res.err
}
func (memo *Memo) Close() {
close(memo.requests)
}
func (memo *Memo) server(f Func) {
cache := make(map[string]*entry)
for req := range memo.requests {
e, ok := cache[req.key]
if !ok {
e = &entry{ready: make(chan struct{})}
cache[req.key] = e
go e.call(f, req.key)
}
go e.deliver(req.response, req.key)
}
}
func (e *entry) call(f Func, key string) {
fmt.Println("request url: ", key)
e.res.value, e.res.err = f(key)
close(e.ready)
}
func (e *entry) deliver(response chan<- result, key string) {
fmt.Println(key, " has been cached!")
<-e.ready
response <- e.res
}
// 上面是cache包
package main
import (
"fmt"
"github.com/zhumaohua/cache"
"io/ioutil"
"log"
"net/http"
"sync"
"time"
)
func incomingUrls() []string {
return []string{"https://www.segmentfault.com", "https://www.baidu.com", "http://www.sogou.com", "http://che.sogou.com", "http://m.che.sogou.com", "https://www.segmentfault.com", "https://www.baidu.com", "https://www.sogou.com", "http://che.sogou.com", "http://m.che.sogou.com", "https://www.segmentfault.com", "https://www.baidu.com", "https://www.sogou.com", "http://che.sogou.com", "http://m.che.sogou.com"}
}
func httpGetBody(url string) (interface{}, error) {
resp, err := http.Get(url)
if err != nil {
return nil, err
}
defer resp.Body.Close()
return ioutil.ReadAll(resp.Body)
}
func main() {
m := cache.New(httpGetBody)
var n sync.WaitGroup
for _, url := range incomingUrls() {
n.Add(1)
go func(url string) {
defer n.Done()
start := time.Now()
value, err := m.Get(url)
if err != nil {
log.Print(err)
}
fmt.Printf("%s, %s, %d bytes\n", url, time.Since(start), len(value.([]byte)))
}(url)
}
n.Wait()
}
代码是简单的一个可以并发读取的缓存,但是输出如下
有几个地方不明白,首先为什么每次get都命中了缓存,但是其实压根没有缓存啊,不能理解为什么输出了那么多次缓存命中,而且证明缓存根本没发挥作用,因为根本没有降低时间,理论上后面的会是ns级别返回才对,请指教下为什么会这样呢?看着代码没什么问题啊,基本上是照着gopl上面敲的啊
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
为什么每次都命中缓存。你看xxx has been cached这句话是在deliver里面的,deliver无论是缓存还是不缓存都会调用!所以这句话打出来不能说明是不是缓存了。你应该反过来,输出没有缓存的日志,这样应该能理解了:
缓存没发挥作用。我看了下代码,似乎代码没什么问题,你按照我上面的代码加一句
has not been cached!
试试看