我不太了解 golang 通道
在Golang实战开发的过程中,我们经常会遇到一些这样那样的问题,然后要卡好半天,等问题解决了才发现原来一些细节知识点还是没有掌握好。今天编程网就整理分享《我不太了解 golang 通道》,聊聊,希望可以帮助到正在努力赚钱的你。
问题内容goroutines 和 channel 这些天一直困扰着我。我正在 https://github.com/adonovan/gopl.io/tree/master/ch9 查看 memo5 代码。
如果你看memo5的memo.go,有func (e *entry) call(f func, key string)
和func (e *entry) deliver(response chan<- result)
部分。
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/
// See page 278.
// Package memo provides a concurrency-safe non-blocking memoization
// of a function. Requests for different keys proceed in parallel.
// Concurrent requests for the same key block until the first completes.
// This implementation uses a monitor goroutine.
package memo
//!+Func
// Func is the type of the function to memoize.
type Func func(key string) (interface{}, error)
// A result is the result of calling a Func.
type result struct {
value interface{}
err error
}
type entry struct {
res result
ready chan struct{} // closed when res is ready
}
//!-Func
//!+get
// A request is a message requesting that the Func be applied to key.
type request struct {
key string
response chan<- result // the client wants a single result
}
type Memo struct{ requests chan request }
// New returns a memoization of f. Clients must subsequently call Close.
func New(f Func) *Memo {
memo := &Memo{requests: make(chan request)}
go memo.server(f)
return memo
}
func (memo *Memo) Get(key string) (interface{}, error) {
response := make(chan result)
memo.requests <- request{key, response}
res := <-response
return res.value, res.err
}
func (memo *Memo) Close() { close(memo.requests) }
//!-get
//!+monitor
func (memo *Memo) server(f Func) {
cache := make(map[string]*entry)
for req := range memo.requests {
e := cache[req.key]
if e == nil {
// This is the first request for this key.
e = &entry{ready: make(chan struct{})}
cache[req.key] = e
go e.call(f, req.key) // call f(key)
}
go e.deliver(req.response)
}
}
func (e *entry) call(f Func, key string) {
// Evaluate the function.
e.res.value, e.res.err = f(key)
// Broadcast the ready condition.
close(e.ready)
}
func (e *entry) deliver(response chan<- result) {
// Wait for the ready condition.
<-e.ready
// Send the result to the client.
response <- e.res
}
//!-monitor
我不明白 close(e.ready)
和 <-e.ready
在这里如何同步。即使读完书,我还是不明白。请告诉我这个机制是什么。
正确答案
e.ready
更广为人知的名称是 done
通道。这是一种通过关闭 done
(e.ready
chan) 来告诉您的 ref 函数 domething 已准备就绪的方法。 <-e.ready
将阻塞,直到它的 done
(lined
)。
所以...阅读这段代码意味着下一步。
deliver
等待红色信号。call
获取 e.res的数据(
e.res.value, e.res.err = f(key)`)call
通过关闭通道来释放已完成的通道 (close(e.ready)
)deliver
可以通过从<-e.ready
读取块并将数据发送到response
今天关于《我不太了解 golang 通道》的内容介绍就到此结束,如果有什么疑问或者建议,可以在编程网公众号下多多回复交流;文中若有不正之处,也希望回复留言以告知!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341