go - 从go例程中堆叠数据

标签 go concurrency goroutine

我正在学习go lang,我想创建一个go应​​用来实现以下目的:

  • 从远程日志
  • 接收数据
  • 分析警告
  • 的某种错误
  • 定期将HTTP请求发送到URL,以通知一切正常或发送警告和错误。

  • 我一直在阅读有关并发性,并行性和 channel 的信息,但是我不确定如何将数据从我的日志记录goroutine传递到另一个带有计时器的例程来发出请求。我是否应该在另一个例程中声明一个分片以接收所有消息,并在计时器结束时对其进行迭代?

    目前,我的代码如下所示:
    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()
    }
    

    最佳答案

    我是否应该在另一个例程中声明一个片以接收所有
    消息,最后计时器会对其进行迭代?


    这是一种非常常见的模式。您描述的示例有时称为“monitor routine”。它保护日志缓冲区,并且因为它“拥有”它们,所以您知道它们可以防止并发访问。

    数据是通过 channel 共享的,日志数据的产生者将与发送者的使用方式完全分离,它所要做的就是在 channel 上发送。如果 channel 没有缓冲,那么您的生产者将阻塞,直到接收者可以处理为止。如果需要保持生产者高吞吐量,则可以缓冲channel或shed sends,如下所示:

    select {
       case logChan <- log:
          ...
       default:
         // chan is full shedding data.
    }
    

    这种模式也非常适合在输入 channel ,计时器和某种完成/上下文中通过for...selects进行的“接收”循环。以下不是一个有效的示例,它缺少取消和逻辑,但是它说明了如何在多个 channel 上进行选择(其中一个是计时器/心跳):
    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
          }
       }
    }()
    

    另外,根据您使用数据的方式,在此处使用实际缓冲区而不是 slice 可能更有意义。

    关于go - 从go例程中堆叠数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61372908/

    相关文章:

    java - Java 中有 ResolvedFuture 类吗?

    戈朗 : calculate how many goroutines are started by worker itself?

    go - 无法分配给结构字段/分配给 nil 映射中的条目

    reactjs - golang模板中不想使用 '{{ }}'怎么办?

    go - 在 Go 中检测有符号整数溢出

    security - 使用 crypto/* 后安全地将缓冲区清零

    c++ - 对包含整数的文本文件进行排序,必须逐行进行排序

    java - 在另一个线程中等待 Future 结果

    关闭 Go channel 时的​​ Go 竞争条件

    go - 从 goroutine 更改变量