Golang中http.HandleFunc与变量更新的问题探讨

Golang中http.HandleFunc与变量更新的问题探讨 你好,

我目前遇到了一个问题,似乎找不到解决方案。我确信这是可能的,只是不知道具体方法。

我的代码是一个API客户端,能够成功从某些第三方服务器获取数据。我有一个函数会持续更新所需的AccessToken,类似于这样:

go refresh_scheduler(mycreds, mytokens, refchan)
for newtokens := range refchan {
        mytokens.AccessToken = newtokens.AccessToken
        mytokens.RefreshToken = newtokens.RefreshToken
}

因此,通过使用通道,我的 main() 函数会定期接收更新后的令牌,这工作正常。

现在我想通过HTTP公开获取的数据,所以我设置了一个非常简单的HandleFunc,如下所示:

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { data_overview(w, r, mytokens, localsid) } )

程序启动后,调用基本URL会给我有效数据。然而,几分钟后,mytokens 结构体被更新(通过通道),但HandleFunc仍然使用旧值,因此调用失败。

我已经尝试在 for 循环内部“更新” HandleFunc,但这似乎没有任何作用。看起来它只在初始化时获取 mytokens 的值,之后就固定了。

任何提示和评论都将不胜感激。

此致, Lordy


更多关于Golang中http.HandleFunc与变量更新的问题探讨的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

好的,我明白了。我将把提供的HTML内容转换为Markdown格式,并严格遵守您列出的所有规则:翻译英文文本、保持代码原样并用正确的代码块包裹、移除用户和日期信息,并只输出最终结果。

好的,我自己已经设法解决了这个问题。

实际上存在两个问题。第一个问题是 `http.ListenAndServer` 是一个阻塞调用,这阻止了其他代码的执行。
第二个问题是,我显然忘记了指针。使用指针后,对更新后的令牌的引用就能正确传递了。

更多关于Golang中http.HandleFunc与变量更新的问题探讨的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go的http.HandleFunc中,闭包捕获的是变量的引用,但这里的问题在于mytokens是一个结构体实例,闭包捕获的是该实例的副本(值捕获)。当你在main函数中更新mytokens的字段时,闭包内持有的副本并不会自动同步更新。解决这个问题的标准做法是使用指针或原子操作来确保并发安全的数据访问。

以下是修改后的示例代码,使用指针和sync.RWMutex来安全地共享和更新令牌:

package main

import (
    "net/http"
    "sync"
)

type Tokens struct {
    AccessToken  string
    RefreshToken string
    mu           sync.RWMutex
}

func (t *Tokens) Update(newAccess, newRefresh string) {
    t.mu.Lock()
    defer t.mu.Unlock()
    t.AccessToken = newAccess
    t.RefreshToken = newRefresh
}

func (t *Tokens) Get() (string, string) {
    t.mu.RLock()
    defer t.mu.RUnlock()
    return t.AccessToken, t.RefreshToken
}

func main() {
    mytokens := &Tokens{}
    refchan := make(chan []string)

    go refresh_scheduler(mycreds, mytokens, refchan)

    go func() {
        for newtokens := range refchan {
            mytokens.Update(newtokens[0], newtokens[1])
        }
    }()

    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        accessToken, refreshToken := mytokens.Get()
        data_overview(w, r, accessToken, refreshToken, localsid)
    })

    http.ListenAndServe(":8080", nil)
}

在这个修改中:

  1. Tokens结构体添加了sync.RWMutex字段来管理并发访问。
  2. 提供了UpdateGet方法,分别用于安全地更新和获取令牌。
  3. HandleFunc中的闭包调用mytokens.Get()来获取最新的令牌值,而不是直接引用可能过期的副本。
  4. refresh_scheduler函数通过通道发送新令牌,然后在单独的goroutine中更新mytokens

这样,每次HTTP请求处理时都会获取当前最新的令牌值,解决了数据不同步的问题。同时,读写锁确保了在更新令牌时不会与并发的HTTP请求发生数据竞争。

回到顶部