我不太理解 golang 的通道(channel)。

huangapple go评论105阅读模式
英文:

I don't understand the golang channel well

问题

close(e.ready) and <-e.ready are used to synchronize the goroutines in the memo package.

In the code you provided, close(e.ready) is called in the call method of the entry struct. This line of code is responsible for broadcasting the "ready" condition to all goroutines waiting on the e.ready channel. By closing the channel, it indicates that the result is ready and any goroutine waiting on this channel can proceed.

On the other hand, <-e.ready is called in the deliver method of the entry struct. This line of code is used to wait for the "ready" condition. When this line is executed, the goroutine will block until another goroutine closes the e.ready channel. Once the channel is closed, the goroutine will continue executing and send the result to the client through the response channel.

In summary, close(e.ready) is used to signal that the result is ready, and <-e.ready is used to wait for the result to be ready before proceeding. This synchronization mechanism ensures that the result is delivered to the client only when it is available.

英文:

Goroutines and channels are bothering me these days. I'm looking at the memo5 code at https://github.com/adonovan/gopl.io/tree/master/ch9.
If you look at memo.go of memo5, there are func (e *entry) call(f Func, key string) and func (e *entry) deliver(response chan&lt;- result) parts.

// Copyright &#169; 2016 Alan A. A. Donovan &amp; 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&lt;- 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 := &amp;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 &lt;- request{key, response}
	res := &lt;-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 = &amp;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&lt;- result) {
	// Wait for the ready condition.
	&lt;-e.ready
	// Send the result to the client.
	response &lt;- e.res
}

//!-monitor

I don't understand how close(e.ready) and &lt;-e.ready synchronize here. Even after reading the book, I don't understand. Please tell me what the mechanism is.

答案1

得分: 1

e.ready更常被称为done通道。这是一种通过关闭donee.ready通道)来告诉您的引用函数某个东西已经准备好的方法。<-e.ready将会阻塞,直到done(关闭)。

所以...阅读这段代码的意思是:

1)deliver等待准备好的信号。
2)call获取e.res的数据(e.res.value, e.res.err = f(key))。
3)call通过关闭它来释放done通道(close(e.ready))。
4)deliver可以通过从<-e.ready阻塞读取并将数据发送到response

英文:

e.ready is more known as done channel. this is a way to tell your ref functions that domething is ready by closing done (e.ready chan). &lt;-e.ready is going to block until its done (closed).

so... reading this code it means next.

  1. deliver waits for rediness signal.
  2. call gets data for e.res (e.res.value, e.res.err = f(key)`)
  3. call releas done channel by closing it (close(e.ready))
  4. deliver can move throu block reading from &lt;-e.ready and send data to response

huangapple
  • 本文由 发表于 2022年2月13日 23:13:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/71101998.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定