Golang中如何在一个for循环结束后重新开始循环?
Golang中如何在一个for循环结束后重新开始循环? 我有一个 main 函数
func main() {
response, err := http.Get(geturl)
if err != nil {
fmt.Print(err.Error())
os.Exit(1)
}
responseData, err := ioutil.ReadAll(response.Body)
if err != nil {
log.Fatal(err)
}
values := gjson.Get(string(responseData), "items")
rl := ratelimit.New(3)
prev := time.Now()
values.ForEach(func(_, v gjson.Result) bool {
now := rl.Take()
url := v.Get("url").String()
resp, err := http.Post(url, "application/x-www-form-urlencoded", nil)
.......
.........
............
return true
})
defer time.AfterFunc(3*time.Second, main())
}
超时后调用 main 函数不起作用…
但总的来说,为了从 geturl 获取新结果而重复 for 循环是正确的解决方案吗?
还有为什么超时后 main() 没有被调用?
另外,我可以用 goroutine 来提高 foreach 循环的性能吗?在这种情况下,goroutine 有帮助吗?
更多关于Golang中如何在一个for循环结束后重新开始循环?的实战教程也可以访问 https://www.itying.com/category-94-b0.html
2 回复
在Golang中,要在for循环结束后重新开始循环,有几种方法可以实现。你的代码中存在几个问题,特别是defer time.AfterFunc(3*time.Second, main())这行代码。
问题分析
-
defer time.AfterFunc的问题:defer会在函数返回时执行,但main()函数通常不会返回main()作为参数传递时会被立即执行,而不是延迟执行
-
重新开始循环的正确方法: 使用无限循环配合定时器
解决方案
方案1:使用无限循环和定时器
func main() {
for {
processData()
time.Sleep(3 * time.Second)
}
}
func processData() {
response, err := http.Get(geturl)
if err != nil {
fmt.Print(err.Error())
return // 返回而不是退出,以便下次循环继续
}
defer response.Body.Close()
responseData, err := ioutil.ReadAll(response.Body)
if err != nil {
log.Println(err)
return
}
values := gjson.Get(string(responseData), "items")
rl := ratelimit.New(3)
values.ForEach(func(_, v gjson.Result) bool {
rl.Take()
url := v.Get("url").String()
resp, err := http.Post(url, "application/x-www-form-urlencoded", nil)
if err != nil {
log.Println(err)
return true
}
defer resp.Body.Close()
// 处理响应...
return true
})
}
方案2:使用ticker控制循环间隔
func main() {
ticker := time.NewTicker(3 * time.Second)
defer ticker.Stop()
for range ticker.C {
processData()
}
}
关于goroutine优化
是的,可以使用goroutine来提高foreach循环的性能,但需要注意并发控制和速率限制:
func processDataWithGoroutines() {
response, err := http.Get(geturl)
if err != nil {
fmt.Print(err.Error())
return
}
defer response.Body.Close()
responseData, err := ioutil.ReadAll(response.Body)
if err != nil {
log.Println(err)
return
}
values := gjson.Get(string(responseData), "items")
// 使用带缓冲的channel控制并发
sem := make(chan struct{}, 10) // 最大10个并发
var wg sync.WaitGroup
values.ForEach(func(_, v gjson.Result) bool {
wg.Add(1)
go func(v gjson.Result) {
defer wg.Done()
sem <- struct{}{} // 获取信号量
defer func() { <-sem }() // 释放信号量
url := v.Get("url").String()
resp, err := http.Post(url, "application/x-www-form-urlencoded", nil)
if err != nil {
log.Println(err)
return
}
defer resp.Body.Close()
// 处理响应...
}(v)
return true
})
wg.Wait() // 等待所有goroutine完成
}
完整示例代码
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"sync"
"time"
"github.com/tidwall/gjson"
)
const geturl = "your_api_endpoint"
func main() {
ticker := time.NewTicker(3 * time.Second)
defer ticker.Stop()
for range ticker.C {
processDataWithGoroutines()
}
}
func processDataWithGoroutines() {
response, err := http.Get(geturl)
if err != nil {
log.Printf("HTTP GET error: %v", err)
return
}
defer response.Body.Close()
responseData, err := ioutil.ReadAll(response.Body)
if err != nil {
log.Printf("Read response error: %v", err)
return
}
values := gjson.Get(string(responseData), "items")
// 控制并发数量
sem := make(chan struct{}, 5)
var wg sync.WaitGroup
var mu sync.Mutex
var successCount, errorCount int
values.ForEach(func(_, v gjson.Result) bool {
wg.Add(1)
go func(v gjson.Result) {
defer wg.Done()
sem <- struct{}{}
defer func() { <-sem }()
url := v.Get("url").String()
resp, err := http.Post(url, "application/x-www-form-urlencoded", nil)
if err != nil {
mu.Lock()
errorCount++
mu.Unlock()
log.Printf("POST error for URL %s: %v", url, err)
return
}
defer resp.Body.Close()
mu.Lock()
successCount++
mu.Unlock()
// 可以在这里处理响应体
}(v)
return true
})
wg.Wait()
log.Printf("Batch completed: %d success, %d errors", successCount, errorCount)
}
这个解决方案会每3秒重新获取数据并处理,使用goroutine提高并发性能,同时通过信号量控制最大并发数避免资源耗尽。


