我有 json 文件,其中有数千条记录作为键值对,我通过将其解码为接口(interface)来读取这些记录。
var devices map[string]interface{} //globalscope in app
jsonFast:= jsoniter.ConfigFastest
_, b, _, _ := runtime.Caller(0)
dir := filepath.Dir(b)
jsonFile, _ := ioutil.ReadFile(dir + "/devices.json")
_ = jsonFast.Unmarshal(jsonFile, &devices)
在高负载下的应用程序过程中,多个 goroutine 会访问它。
现在由于这个文件每 5 分钟更新一次,所以在不重新启动应用程序的情况下,我想使这个 map 界面无效
devices
从文件中加载新数据。在 node.js 中,我曾经使用
delete require.cache[require.resolve("filename")]
但不确定如何在 go 中完成此操作。我尝试在 SetInterval func(节点版本的端口)中使用互斥锁,我从 here 使用每 5 分钟读取一次文件,但出现此错误:
goroutine 871895 [IO wait]:
这似乎意味着 goroutine 正在等待解锁以从全局变量中读取。代码:
var m sync.Mutex
//this function execute every 5 minute to read file and reassign to map interface.
_ = setInterval(func() {
jsonFile, _ := ioutil.ReadFile(dir + "/devices.json")
m.Lock() // used this mutex as the step may cause race condition.
_ = jsonFast.Unmarshal(jsonFile, &devices)
m.Unlock()
}, 5* 60 * 1000, false)
//this initializes at the start after which the set interval execute every 5 minute to get updated data.
jsonFile, _ := ioutil.ReadFile(dir + "/devices.json")
_ = jsonFast.Unmarshal(jsonFile, &devices)
我应该用什么方法来实现这一点?或者有什么方法可以从文件中读取/更新而不是使用映射接口(interface)来避免竞争条件和 IO 锁定?
最佳答案
我想这个问题与当你试图用新数据覆盖它时你仍然有从 map 中读取的 goroutines 的事实有关。我建议您使用 sync.RWMutex
保护它,并这样做:
type GlobalState struct {
data map[string]interface{}
sync.RWMutex
}
func (gs *GlobalState) Get(key string) interface{} {
gs.RLock()
defer gs.RUnlock()
return gs.data[key]
}
func (gs *GlobalState) Refresh() {
jsonFile, _ := ioutil.ReadFile(dir + "/devices.json")
gs.Lock()
defer gs.Unlock()
_ = jsonFast.Unmarshal(jsonFile, &gs.data)
}
var devices GlobalState
func main() {
t := time.NewTicker(5 * 60 * time.Second)
for ; true; <-t.C {
devices.Refresh()
}
}
然后你有安全读取(但需要做
devices.Get(key)
而不是 devices[key]
)和安全写入。此外,最后它被清理了一点,因此您不必重复代码以使计时器立即运行。
关于go - 更新全局范围变量值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59779035/