英文:
How to run a golang function call once per key parameter in concurrent environment?
问题
这个例子似乎只会获取一次数据,但我不认为它会同时为每个key
在后台调用fetchDataInBackground
函数。
我需要做的是将每个Once
实例分配给一个key
,以便可以同时获取不同key
的所有数据。我该怎么做?
英文:
This example seems to fetch data once, but I don't think it will invoke a fetchDataInBackground
function in background for each key
concurrently.
func Get(key string){
...
if itIsTheTimeToRefreshData{
var once sync.Once
onceBody := func() {
fetchDataInBackground()
}
go func() {
once.Do(onceBody)
}()
}
...
}
what I need to do is to assign each Once
instance to a key
so that all fetch data for different keys can be done concurrently.
how do I do that?
答案1
得分: 4
我认为sync.Once
对于这样的任务不太适用。你需要为每个键维护一些标志("once"),使用互斥访问的映射是可能的解决方案之一。
完整的工作示例:
package main
import (
"fmt"
"sync"
"time"
)
var once map[string]bool
var onceMutex sync.Mutex
var itIsTheTimeToRefreshData = true
func Get(key string) {
fmt.Printf("访问键:%s\n", key)
if itIsTheTimeToRefreshData {
onceBody := func() {
fmt.Printf("只有一次的键:%s\n", key)
// 在后台获取数据
}
onceMutex.Lock()
if !once[key] { // 第一次访问?
once[key] = true
onceMutex.Unlock()
// 在这里刷新一些内容
go onceBody()
} else {
onceMutex.Unlock()
}
}
}
func main() {
once = make(map[string]bool)
// 并行地第一次访问
for i := 0; i < 10; i++ {
key := fmt.Sprintf("i%d", i)
go func(key string) {
Get(key)
}(key)
}
// 第二次访问
for i := 0; i < 10; i++ {
key := fmt.Sprintf("i%d", i)
go func(key string) {
Get(key)
}(key)
}
fmt.Println("所有请求已完成。")
time.Sleep(1 * time.Second)
}
希望对你有帮助!
英文:
I think sync.Once
is not well for such task. You need to maintain some flag ("once") for each key individually. Map with mutexed access is one of possible solutions.
Full working example:
package main
import (
"fmt"
"sync"
"time"
)
var once map[string]bool
var onceMutex sync.Mutex
var itIsTheTimeToRefreshData = true
func Get(key string) {
fmt.Printf("Access for key: %s\n", key)
if itIsTheTimeToRefreshData {
onceBody := func() {
fmt.Printf("Only once for key: %s\n", key)
//fetchDataInBackground()
}
onceMutex.Lock()
if !once[key] { // is it first time?
once[key] = true
onceMutex.Unlock()
// refresh something here
go onceBody()
} else {
onceMutex.Unlock()
}
}
}
func main() {
once = make(map[string]bool)
// do it first time in parallel
for i := 0; i < 10; i++ {
key := fmt.Sprintf("i%d", i)
go func(key string) {
Get(key)
}(key)
}
// and another time
for i := 0; i < 10; i++ {
key := fmt.Sprintf("i%d", i)
go func(key string) {
Get(key)
}(key)
}
fmt.Println("All requested.")
time.Sleep(1 * time.Second)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论