为了账号安全,请及时绑定邮箱和手机立即绑定

偶尔的“切片范围超出范围”恐慌

偶尔的“切片范围超出范围”恐慌

Go
慕侠2389804 2022-09-12 21:15:00
我正在运行一个将网络钩子转发到网络平台的脚本。将 Webhook 发送到 WebSocket 的部件会检查非活动连接,并在转发 Webhook 时尝试删除它们,有时会失败并显示以下错误:http: panic serving 10.244.38.169:40958: runtime error: slice bounds out of range(IP/端口总是不同的,这只是一个示例。相关代码:// Map holding all Websocket clients and the endpoints they are subscribed tovar clients = make(map[string][]*websocket.Conn)var upgrader = websocket.Upgrader{}// function to execute when a new client connects to the websocketfunc handleClient(w http.ResponseWriter, r *http.Request, endpoint string) {    conn, err := upgrader.Upgrade(w, r, nil)    // ...    // Add client to endpoint slice    clients[endpoint] = append(clients[endpoint], conn)}// function to send a webhook to a websocket endpointfunc handleHook(w http.ResponseWriter, r *http.Request, endpoint string) {    msg := Message{}    // ...       // Get all clients listening to the current endpoint    conns := clients[endpoint]    if conns != nil {        for i, conn := range conns {            if conn.WriteJSON(msg) != nil {                // Remove client and close connection if sending failed                conns = append(conns[:i], conns[i+1:]...)   // this is the line that sometimes triggers the panic                conn.Close()            }        }    }    clients[endpoint] = conns}我不明白为什么迭代连接并附加它们有时会引发恐慌。
查看完整描述

1 回答

?
蓝山帝景

TA贡献1843条经验 获得超7个赞

我想说的几点:

  1. 确保您的程序没有争用条件(例如。 是全局可访问的,如果同时进行读/写或写/写,则应受到保护)。clients

  2. 在切片上划线时,您不需要检查非nil切片是否已经处理了该范围(请参阅我共享的代码)。for [...] range [...]

  3. 它有时会发生在您的身上,因为有时失败并返回错误,并且在范围越广时删除元素的错误逻辑使您的程序恐慌。(请参阅我共享的代码)conn.WriteJSON

package main


import "fmt"


func main() {

    var conns []string = nil


    // "if conns != nil" check is not required as "for [...] range [...]"

    // can handle that. It is safe to use for "range" directly.

    for i, conn := range conns {

        fmt.Println(i, conn)

    }


    conns = []string{"1", "2", "3"}

    

    // Will panic

    for i := range conns {

        fmt.Printf("access: %d, length: %d\n", i, len(conns))

        conns = append(conns[:i], conns[i+1:]...)

    }

}

在此示例中,您可以看到您尝试访问的索引大于或等于触发 panic 的切片的长度。我认为这个答案应该可以帮助您纠正逻辑,或者您也可以使用地图来存储连接,但它再次带有自己的警告,例如没有排序保证,即它从地图中读取的顺序。


查看完整回答
反对 回复 2022-09-12
  • 1 回答
  • 0 关注
  • 129 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信