dongyuan1984 2016-12-04 20:05
浏览 40
已采纳

Golang-在风扇上排序

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条回答 默认 最新

  • drpmazn9021 2016-12-04 20:29
    关注

    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.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?