本文介绍如何使用 go 语言读取含 url 和间隔时间的配置文件,通过 ticker 定期发起 http 请求并统计响应耗时与状态码,同时规避 goroutine 闭包陷阱和文件解析错误。
本文介绍如何使用 go 语言读取含 url 和间隔时间的配置文件,通过 ticker 定期发起 http 请求并统计响应耗时与状态码,同时规避 goroutine 闭包陷阱和文件解析错误。
在 Go 中构建一个轻量级 HTTP 健康检查工具,关键在于:正确解析配置、安全并发执行请求、避免变量捕获错误、合理管理资源与超时。原代码存在多个典型问题:
- ❌ 文件按 \t 一次性分割,导致 URL 和时间混杂(如 "http://google.com\t5\nhttp://nike.com\t10" 分割后为 ["http://google.com 5 \nhttp://nike.com 10"],而非预期的多行);
- ❌ for i := 0; i
- ❌ defer resp.Body.Close() 写在 if err != nil 分支外但未加 resp != nil 判断,当请求失败时 resp 为 nil,触发 panic;
- ❌ in channel 被声明却未被任何 goroutine 消费,且 wg.Wait() 在无限 ticker 循环内永不执行,逻辑阻塞。
以下是修复后的完整可运行示例:
package main
import (
"bufio"
"fmt"
"io"
"log"
"net/http"
"os"
"strconv"
"strings"
"sync"
"time"
)
// URLWithInterval 表示一条带轮询间隔(秒)的 URL 记录
type URLWithInterval struct {
URL string
Interval time.Duration
}
// parseURLFile 解析形如 "https://example.com\t30" 的文本文件,每行一条记录
func parseURLFile(filename string) ([]URLWithInterval, error) {
file, err := os.Open(filename)
if err != nil {
return nil, fmt.Errorf("failed to open %s: %w", filename, err)
}
defer file.Close()
var urls []URLWithInterval
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if line == "" || strings.HasPrefix(line, "#") {
continue // 跳过空行和注释
}
parts := strings.Split(line, "\t")
if len(parts) <p>? <strong>关键改进说明:</strong> </p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/ai/4015" title="Stitch"><img
src="https://img.php.cn/upload/ai_manual/001/246/273/178599596114216.png" alt="Stitch" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/ai/4015" title="Stitch" class="overflowclass">Stitch</a>
<p class="overflowclass">Stitch是一款AI图像与设计工具,Google Labs 推出的 AI 原生设计工具。</p>
</div>
<a rel="nofollow" href="/ai/4015" title="Stitch" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
- ✅ 健壮文件解析:使用 bufio.Scanner 按行读取,再对每行 strings.Split(..., "\t"),明确区分 URL 与间隔;支持跳过空行/注释;
- ✅ goroutine 安全:for _, u := range urls 中直接传值 u 到 goroutine,避免闭包捕获循环变量;
- ✅ HTTP 安全调用:checkURL 函数内统一处理 err 与 resp,仅在 resp != nil 时调用 Close();显式设置 http.Client.Timeout 防止 hang;
- ✅ 职责分离:monitorURL 封装单 URL 的长期监控逻辑,主函数专注调度与初始化;
- ✅ 可观测性:清晰日志格式,包含时间戳、状态、耗时,便于运维排查。
⚠️ 注意事项:
- 确保 url_list.txt 使用真实 Tab 字符分隔(非空格),可用 cat -A url_list.txt 验证;
- 生产环境建议增加重试机制、结果聚合(如 Prometheus 指标暴露)、失败告警;
- 若需并发控制(如限制最大并发请求数),可引入 semaphore 或 worker pool 模式,而非无限制启动 goroutine。
该方案简洁、可靠、符合 Go 最佳实践,适用于服务健康巡检、SLA 监控等场景。










