根据Go lang中的类型处理案件的更好方法

时间:2019-02-21 09:17:09

标签: go

我是Go语言的新手,我可以就如何重构代码使用一些建议。我要做的只是取决于Sarama的成功或失败(Apache Kafka正在进行中),我需要登录并进一步转发它。到目前为止,我的代码看起来像这样

go func() {
    for err := range producer.Errors() {
        batchID := err.Msg.Metadata.(ackMeta).batchID # notice the struct here
        statusChan := err.Msg.Metadata.(ackMeta).statusChan
        statusChan <- false
        close(statusChan)
        logs.Debug(appName, "Signalled failure on statusChan for batch ", batchID)
        logs.Error(appName, "Failed to publish data to analyzer for batchID: ", batchID, err)
    }
}()

go func() {
    for succ := range producer.Successes() {
        batchID := succ.Metadata.(ackMeta).batchID        # notice the struct here
        statusChan := succ.Metadata.(ackMeta).statusChan
        statusChan <- true
        close(statusChan)
        logs.Debug(appName, "Signalled success on statusChan for batch ", batchID)
        logs.Debug(appName, "Successfully  published data to analyzer:", succ.Topic, succ.Key, succ.Partition, succ.Offset, succ.Metadata)
    }

我认为我可以做得更好,并将整个内容包装在一个函数中,但是到目前为止,除了使用此处所示的切换用例之外,我再也没有想到其他任何东西

func checkSuccessOrFailAck(msg interface{}) {
    switch msgType := msg.(type) {
    case producer.Errors:
        batchID := msg.Msg.Metadata.(ackMeta).batchID
        statusChan := msg.Msg.Metadata.(ackMeta).statusChan
        statusChan <- false
        close(statusChan)
        logs.Debug(appName, "Signalled failure on statusChan for batch ", batchID)
        logs.Error(appName, "Failed to publish data to analyzer for batchID: ", batchID, msg)
    case producer.Successes:
        batchID := msg.Metadata.(ackMeta).batchID
        statusChan := msg.Metadata.(ackMeta).statusChan
        statusChan <- true
        close(statusChan)
        logs.Debug(appName, "Signalled success on statusChan for batch ", batchID)
        logs.Debug(appName, "Successfully  published data to analyzer:", succ.Topic, succ.Key, succ.Partition, succ.Offset, succ.Metadata)
    }

}

消息的类型不同,因此我从消息中提取属性的方式也不同。但是我对这种方法不满意,因为声明比前一种更多。有没有更好的思维方式去写作?

2 个答案:

答案 0 :(得分:1)

首先,不清楚第二个代码是否完全有效。由于Errors()Successes()返回通道,因此您需要select同时读取它们两个,而不会阻塞它们。

由于succerr在代码中具有不同的类型,因此我不确定您可以比原始示例做得短得多。 Go还没有泛型,因此编写将两者统一的代码具有挑战性。如果您确实需要它,那么我将尝试查找类型相同的最接近点-从那时起,更容易统一代码。例如err.Msgsucc是同一类型?

此外,即使Go已经拥有仿制药,也不清楚统一这些仿制药是否会成功。 Go的理念是,稍微重复代码比过度复杂的抽象要好。该代码并不是理论上最短的代码,但它是明确而清晰的。

答案 1 :(得分:0)

您可以使用$在单个goroutine中将它们都做:

select

这将一直循环直到两个通道都被关闭为止,并且在每次循环迭代时,都从一个有等待接收值的通道中处理一个值(或者如果两个都有等待的值,则随机选择一个)。