英文:
Golang - Sorting on fan in
问题
我正在随机生成一堆日志消息,生成后,我需要按时间戳对它们进行排序,然后将它们写入日志。我正在利用sort
库的sort.Interface
特性,以便根据时间戳进行排序。我正在使用一个并发设计的扇入模式,所以我的排序函数会聚合所有来自goroutine的日志消息,然后对它们进行排序。
以下是我的代码:
type CommonLogFormat struct {
HostIP string
UserIdent string
User string
Timestamp string
Request string
HttpStatusCode int
Size int
}
type Logs struct {
Messages []*CommonLogFormat
}
func sortByTimestamp(ch chan<- *CommonLogFormat) *Logs {
logs := &Logs{Messages: make([]*CommonLogFormat, 0)}
for i := range ch {
logs.Messages = append(logs.Messages, i)
}
sort.Sort(logs)
return logs
}
func (l Logs) Len() int {
return len(l.Messages)
}
func (l Logs) Less(i, j int) bool {
return l.Messages[i].Timestamp < l.Messages[j].Timestamp
}
func (l *Logs) Swap(i, j int) {
l.Messages[i], l.Messages[j] = l.Messages[j], l.Messages[i]
}
然而,当我尝试从通道接收日志消息时,我遇到了以下错误:
invalid operation: <-i (receive from non-chan type *CommonLogFormat)
为什么我无法从通道接收值?
英文:
I am randomly generating a bunch of log messages, and after they have been generated, I need to sort them by timestamp before writing them to the logs. I'm utilising the sort.Interface
aspect of the sort
library so I can sort based on my timestamp. I'm using a fan-in concurrency design, so my sorting function aggregates all the log messages from the goroutines, then sorts them.
Here is my code:
type CommonLogFormat struct {
HostIP string
UserIdent string
User string
Timestamp string
Request string
HttpStatusCode int
Size int
}
type Logs struct {
Messages []*CommonLogFormat
}
func sortByTimestamp(ch chan <- *CommonLogFormat) *Logs {
logs := &Logs{Messages: make([]*CommonLogFormat, 1)}
for i := range ch {
logs.Messages = append(logs.Messages, <- i)
}
sort.Sort(logs)
return logs
}
func (l Logs) Len() int {
return len(l.Messages)
}
func (l Logs) Less(i,j int) bool {
return l.Messages[i].Timestamp < l.Messages[j].Timestamp
}
func (l *Logs) Swap(i,j int) {
l.Messages[i], l.Messages[j] = l.Messages[j], l.Messages[i]
}
However, when I go to receive a log message from the channel, I get this error:
invalid operation: <-i (receive from non-chan type *CommonLogFormat)
Why can't I receive a value from the channel?
答案1
得分: 2
我认为错误信息已经很明显了。看看这段代码:
for i := range ch {
logs.Messages = append(logs.Messages, <-i)
}
ch
的类型是 chan<- *CommonLogFormat
,也就是一个通道。for range
循环遍历通道,将通道中发送的值存储在循环变量 i
中。i
不是一个通道,而是通道中发送的值,所以它的类型是 *CommonLogFormat
。
所以没有必要,也不能从中接收,因为它已经是你想要接收的值了。只需简单地将 i
追加到 logs.Messages
中:
for i := range ch {
logs.Messages = append(logs.Messages, i)
}
在 规范:For 语句 中详细说明了在 for range
的情况下循环变量的含义:
Range 表达式 第一个值 第二个值
数组或切片 a [n]E, *[n]E, or []E 索引 i int a[i] E
字符串 s string 类型 索引 i int 参见下文 rune
映射 m map[K]V 键 k K m[k] V
通道 c chan E, <-chan E 元素 e E
最后一行适用于遍历通道的情况,第一个迭代值是元素。
> 对于通道,产生的迭代值是在通道上发送的连续值,直到通道被关闭为止。如果通道为 `nil`,则 range 表达式将永远阻塞。
[1]: https://golang.org/ref/spec#For_statements
[2]: https://golang.org/ref/spec#Close
英文:
I think the error message is pretty self-explanatory. Look at this:
for i := range ch {
logs.Messages = append(logs.Messages, <- i)
}
ch
is of type chan <- *CommonLogFormat
. ch
is a channel. The for range
loop over the channel yields the values sent on the channel, which will be stored in the loop variable i
. i
is not a channel, but the values sent on the channel, so it will be of type *CommonLogFormat
.
So no need, and you actually can't receive from it, it is already what you would want to receive from it. Simply append i
:
for i := range ch {
logs.Messages = append(logs.Messages, i)
}
The Spec: For statements details what the loop variables are in case of for range
:
Range expression 1st value 2nd value
array or slice a [n]E, *[n]E, or []E index i int a[i] E
string s string type index i int see below rune
map m map[K]V key k K m[k] V
channel c chan E, <-chan E element e E
The last line applies in case of ranging over a channel, and the first iteration value is the element.
> For channels, the iteration values produced are the successive values sent on the channel until the channel is closed. If the channel is nil
, the range expression blocks forever.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论