douhan5853 2016-05-09 11:06
浏览 158

GO-函数返回后代码停止执行

So, I'm trying to construct a websocket server in go. And i ran into this interesting bug, which i cant for the life of me figure out why its happening.

NOTE: The comments in the code snippets are there only for this post. Read them.

Ive got this function:

func Join(ws *websocket.Conn) {
    Log.Connection(ws)

    enc := json.NewEncoder(ws)
    dec := json.NewDecoder(ws)

    var dJ g.DiscussionJoin
    var disc g.Discussion

    Log.Err(dec.Decode(&dJ), "dec.Decode")

    ssD := g.FindDiscussionByID(dJ.DiscussionID)

    ssDJ := dJ.Convert(ws)

    g.DiscHandle <- &ssDJ

    disc = ssD.Convert()

    Log.Err(enc.Encode(disc), "enc.Encode")

    Log.Activity("Discussion", "Joined", disc.DiscussionID.Subject)

    fmt.Println("Listening") //This gets called
    g.Listen(dec)
    fmt.Println("Stoped Listening") //This DOESN'T get called [IT SHOULD]

    ssDJ.SSDiscussion.Leave(ssDJ.SSUserID)

    Log.Disconnection(ws)
}

The function thats causing this is (in my opinion) g.Listen(...):

func Listen(dec *json.Decoder) {
    timeLastSent := time.Now().Second()
    in := Message{}
    for ((timeLastSent + ConnTimeout) % 60) != time.Now().Second() {
        if err := dec.Decode(&in); err != nil {
            continue
        } else if in == Ping {
            timeLastSent = time.Now().Second()
            continue
        }
        timeLastSent = time.Now().Second()
        Messages <- in
        in = Message{}
    }
    fmt.Println("Client timed out!") //This gets called
    return
}

Ive tried both with and without the return on the last row of Listen

As response to @SimoEndre, Ive left the main method out of the code example, but since you mentioned it, this is the function that takes g.Messege{} out of the Messeges channel.
NOTE: MessageHandler() runs on its own go routine.

func MessageHandler() {
    for msg := range Messages {
        for _, disc := range LivingDiscussions {
            if disc.DiscussionID.UDID == msg.UDID {
                go disc.Push(msg)
                break
            }
        }
    }
}
  • 写回答

1条回答 默认 最新

  • dongsimang4036 2016-05-09 11:17
    关注

    Looking at the Listen function you will remark that it has a Messages channel which receive the the Message{} struct, but in the main goroutine it does not get outputted. Remember that goroutines are two way communication channels, which means that if a channel does receive an input value it must have an output value the channel to not block.

    So you need to create a channel with the same struct type as the Message{}

    message := make(chan Message{})
    

    Then in the Join function you have to pop out the value pushed to channel:

    func Join(ws *websocket.Conn) {
        ...
        <-message
    }
    

    Update after new inputs:

    It's not enough to iterate over the values coming from a channel, you need to do this inside a go func().

    Getting the values out of different concurrently executing goroutines can be accomplished with the select keyword, which closely resembles the switch control statement and is sometimes called the communications switch.

    go func() {   
        for msg := range Messages {
            for _, disc := range LivingDiscussions {
                if disc.DiscussionID.UDID == msg.UDID {
                    select {
                    case disc.Push <- msg: // push the channel value to the stack
    
                    default :
                    // default action
                    }
                }
            }
        }
    }()
    

    I don't know how your disc.Push method is implemented, but if the idea is to push the received channel values to a stack you have to modify your code in a way to send back the channel value to the array. In the code snippet above i've just wanted to emphasize that it's important to get the values back pushed into the channel.

    评论

报告相同问题?

悬赏问题

  • ¥500 火焰左右视图、视差(基于双目相机)
  • ¥100 set_link_state
  • ¥15 虚幻5 UE美术毛发渲染
  • ¥15 CVRP 图论 物流运输优化
  • ¥15 Tableau online 嵌入ppt失败
  • ¥100 支付宝网页转账系统不识别账号
  • ¥15 基于单片机的靶位控制系统
  • ¥15 真我手机蓝牙传输进度消息被关闭了,怎么打开?(关键词-消息通知)
  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本