我是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)
}
}
消息的类型不同,因此我从消息中提取属性的方式也不同。但是我对这种方法不满意,因为声明比前一种更多。有没有更好的思维方式去写作?
答案 0 :(得分:1)
首先,不清楚第二个代码是否完全有效。由于Errors()
和Successes()
返回通道,因此您需要select
同时读取它们两个,而不会阻塞它们。
由于succ
和err
在代码中具有不同的类型,因此我不确定您可以比原始示例做得短得多。 Go还没有泛型,因此编写将两者统一的代码具有挑战性。如果您确实需要它,那么我将尝试查找类型相同的最接近点-从那时起,更容易统一代码。例如err.Msg
和succ
是同一类型?
此外,即使Go已经拥有仿制药,也不清楚统一这些仿制药是否会成功。 Go的理念是,稍微重复代码比过度复杂的抽象要好。该代码并不是理论上最短的代码,但它是明确而清晰的。
答案 1 :(得分:0)
您可以使用$
在单个goroutine中将它们都做:
select
这将一直循环直到两个通道都被关闭为止,并且在每次循环迭代时,都从一个有等待接收值的通道中处理一个值(或者如果两个都有等待的值,则随机选择一个)。