Reputation: 1699
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?
Upvotes: 3
Views: 924
Reputation: 417767
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.
Upvotes: 2