Go Channel读写陷入无限循环

问题描述:

First of all, I want to make Long Polling notification system. To be more specific, I will make http request, and response will be returned only if map channel is true.

This is the code block I used:

var MessageNotification = make(map[string]chan bool, 10)

func GetNotification(id int, timestamp int) notification {
    <-MessageNotification["1"]

    var chat_services []*models.Chat_service
    o := orm.NewOrm()

    _, err := o.QueryTable("chat_service").Filter("Sender__id", id).RelatedSel().All(&chat_services)

    if err != nil {
        return notification{Status: false}
    }
    return notification{Status: true, MessageList: chat_services}
}

func SetNotification(id int) {
    MessageNotification[strconv.Itoa(id)] <- true
}

This is controller block :

func (c *ChatController) Notification() {

data := chat.GetNotification(1,0)

c.Data["json"] = data
c.ServeJSON()

  }


func (c *ChatController) Websocket(){


    chat.SetNotification(1)

    c.Data["json"] = "test"
    c.ServeJSON();

}

function names and variable created for test.

No error occurred. Thanks for your help.

You're not creating your channel.

var MessageNotification = make(map[string]chan bool, 10)

This line makes a map with capacity 10, but you're not creating the actual channels in the map. As a result, `SetNotification["1"] is a nil channel, and sends and receives on nil channels block indefinitely.

You need to put in

MessageNotification["1"] = make(chan bool)

You can include a size if desired (and I have a hunch your "10" in the map make was supposed to be the buffering for that channel). This can even be done conditionally:

func GetNotification(id int, timestamp int) notification {
    if _, ok := MessageNotification["1"]; !ok { // if map does not contain that key
        MessageNotification["1"] = make(chan bool, 10)
    }

    <-MessageNotification["1"]
    // ...
}

func SetNotification(id int) {
    if _, ok := MessageNotification[strconv.Itoa(id)]; !ok { // if map does not contain that key
        MessageNotification[strconv.Itoa(id)] = make(chan bool, 10)
    }

    MessageNotification[strconv.Itoa(id)] <- true
}

This way the first location that tries to access the channel adds it to the map and properly makes the channel, so sends and receives on it will actually function.