我正在学习go lang,我想创建一个go app来实现以下功能。
我一直在阅读关于并发、并行和通道的文章,但我不知道应该如何将我的日志记录goroutine中的数据传递给另一个带有定时器的例程来进行请求。 我是否应该在另一个例程中声明一个分片来接收所有的消息,并在最后fo定时器对其进行迭代?
目前,我的代码是这样的。
package main
import (
"fmt"
"log"
"strings"
"gopkg.in/mcuadros/go-syslog.v2"
)
func strigAnalyze(str string){
/*analyse the contents of the log message and do something*/
}
func main() {
channel := make(syslog.LogPartsChannel)
handler := syslog.NewChannelHandler(channel)
server := syslog.NewServer()
server.SetFormat(syslog.RFC3164)
server.SetHandler(handler)
server.ListenUDP("0.0.0.0:8888")
server.ListenTCP("0.0.0.0:8888")
server.Boot()
go func(channel syslog.LogPartsChannel) {
for logParts := range channel {
content := logParts["content"]
fmt.Println("logparts", logParts)
string := fmt.Sprintf("%v", content)
strigAnalyze(str)
}
}(channel)
server.Wait()
}
我是否应该在另一个例程中声明一个分片来接收所有的消息,并在最后fo定时器迭代它?
这是一个非常常见的模式在去。你所描述的例子有时被称为"例行监查". 它守护着日志的缓冲区,因为它 "拥有 "日志,所以你知道它们是安全的,不会被并发访问。
数据是通过通道共享的,日志数据的生产者将与发送者如何使用日志数据完全解耦,它所需要做的就是在通道上发送。如果通道是无缓冲的,那么你的生产者会阻塞,直到接收器可以处理。如果你需要保持生产者的高吞吐量,你可以对通道进行缓冲或 遣送,它看起来像。
select {
case logChan <- log:
...
default:
// chan is full shedding data.
}
这种模式也很适合用于 "接收 "循环,即: for...selects
在输入通道、定时器和某种donecontext上进行选择。以下不是一个工作的例子,它缺少取消和逻辑,但它显示了你如何为...选择多个通道(其中一个是你的定时器心跳)。
logChan := make(chan string)
go func() {
var logBuf []string
t := time.NewTimer(time.Second * 5)
for {
select {
log, ok := <-logChan:
if !ok { return }
logBuf = append(logBuf, log)
<-t.C:
// timer up
// flush logs
// reset slice
}
}
}()
另外,根据你如何使用数据, 在这里使用一个实际的缓冲区而不是切片可能更有意义。