You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从Goroutine向主循环发送事件以实时更新Sway状态栏?

解决方案

你的核心问题是主循环中time.Sleep和channel接收的串行阻塞导致无法实时响应窗口焦点变化,用Go的select语句可以完美解决这个问题,同时兼顾定时更新和事件通知的需求。

修正后的主循环代码

func main(){
    // 带缓冲的channel,避免goroutine因发送阻塞
    title_queue := make(chan string, 1)
    go poll_changes(title_queue)

    title := get_title()
    // 创建每秒触发一次的定时器,替代Sleep
    ticker := time.NewTicker(time.Second)
    defer ticker.Stop() // 程序退出时停止定时器,避免goroutine泄漏

    for {
        select {
        // 处理窗口焦点变化事件
        case newTitle := <-title_queue:
            title = newTitle
            // 收到新标题立即更新状态栏
            update_status_bar(title, get_time())
        // 处理定时更新
        case <-ticker.C:
            update_status_bar(title, get_time())
        }
    }
}

优化后的poll_changes函数

func poll_changes(title chan string) {
    addr := swayipc.Getaddr()
    conn := swayipc.Getsock(addr)
    defer conn.Close() // 确保连接最终被关闭,避免资源泄漏

    events := []string{"window"}
    swayipc.Subscribe(conn, events)

    var result map[string]interface{}
    for {
        response := swayipc.Unpack(conn)
        // 增加JSON解析错误处理
        if err := json.Unmarshal(response, &result); err != nil {
            continue
        }

        // 类型断言时增加安全检查,避免panic
        change, ok := result["change"].(string)
        if !ok || change != "focus" {
            continue
        }

        window, ok := result["container"].(map[string]interface{})
        if !ok {
            continue
        }

        windowName, ok := window["name"].(string)
        if !ok {
            continue
        }

        // 非阻塞发送,确保只保留最新的窗口标题
        select {
        case title <- windowName:
        default:
            // 若主循环未及时接收,丢弃旧标题,不阻塞goroutine
        }
    }
}

关键改动说明

  • 替换time.Sleep为time.Ticker:Ticker会通过channel定时发送信号,不会阻塞整个主循环,配合select实现“多事件监听”。
  • select语句的使用:同时监听定时器channel和标题更新channel,哪个事件先触发就执行对应逻辑,既保证每秒更新状态栏,又能实时响应窗口焦点变化。
  • 带缓冲channel+非阻塞发送:缓冲大小设为1,确保goroutine不会因主循环忙碌而阻塞;非阻塞发送的分支则保证只保留最新的窗口标题,旧的未处理标题会被丢弃,符合状态栏的需求。
  • 安全检查与资源清理:增加类型断言的安全检查避免panic,添加defer语句清理连接和定时器,防止资源泄漏。

关于Go并发模型的说明

你之前用Python的threading.Event实现类似功能,Go中更推荐用channel和select来处理这类并发通知场景,这是Go原生并发模型的核心优势,比Event更简洁且贴合语言特性。

内容的提问来源于stack exchange,提问作者Harsh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 04:55:14