在Go语言中获取TTFB、Connect及Total time值的技术咨询
我来帮你搞定这个问题,分两种方案详细说明:
方案一:基于curl提取数值到Go变量
首先要注意,你原来的代码里c.Run()不会返回命令的输出,得用Output()或者CombinedOutput()来捕获stdout。然后我们可以用正则表达式匹配输出里的数值,再转成Go变量。
修改后的代码示例:
package main import ( "fmt" "os/exec" "regexp" "strconv" ) func main() { // 加了-s参数让curl进入安静模式,避免多余输出干扰解析 c := exec.Command( "curl", "-w", "Connect: %{time_connect} TTFB: %{time_starttransfer} Total time: %{time_total}", "-o", "/dev/null", "-s", "http://my.domain/favicon.ico", ) // 获取命令输出(包含stdout和stderr,方便排查错误) output, err := c.CombinedOutput() if err != nil { fmt.Printf("执行curl命令出错: %v\n输出内容: %s\n", err, output) return } // 用正则匹配三个浮点数值 re := regexp.MustCompile(`Connect: (\d+\.\d+) TTFB: (\d+\.\d+) Total time: (\d+\.\d+)`) matchResults := re.FindStringSubmatch(string(output)) if len(matchResults) != 4 { fmt.Println("无法解析curl的输出内容") return } // 把字符串转成float64变量 connectTime, _ := strconv.ParseFloat(matchResults[1], 64) ttfb, _ := strconv.ParseFloat(matchResults[2], 64) totalTime, _ := strconv.ParseFloat(matchResults[3], 64) // 验证结果 fmt.Printf("Connect时间: %.3f秒\nTTFB: %.3f秒\n总耗时: %.3f秒\n", connectTime, ttfb, totalTime) }
方案二:纯Go实现(完全不依赖curl)
用Go标准库的net/http和httptrace包可以更精准地测量这些时间点,而且不需要外部依赖,跨平台性更好。
代码示例:
package main import ( "fmt" "io" "net/http" "net/http/httptrace" "time" ) func main() { targetURL := "http://my.domain/favicon.ico" requestStart := time.Now() // 定义变量存储关键时间点 var connectStart, connectFinish, firstResponseByte time.Time // 创建HTTP请求 req, err := http.NewRequest(http.MethodGet, targetURL, nil) if err != nil { fmt.Printf("创建请求失败: %v\n", err) return } // 设置HTTP追踪,捕获各个阶段的时间点 trace := &httptrace.ClientTrace{ ConnectStart: func(network, addr string) { connectStart = time.Now() }, ConnectDone: func(network, addr string, err error) { connectFinish = time.Now() }, GotFirstResponseByte: func() { firstResponseByte = time.Now() }, } // 将追踪绑定到请求上下文 req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace)) // 发送请求 client := &http.Client{} resp, err := client.Do(req) if err != nil { fmt.Printf("请求失败: %v\n", err) return } defer resp.Body.Close() // 读取响应体(确保总耗时包含读取响应的时间) _, err = io.Copy(io.Discard, resp.Body) if err != nil { fmt.Printf("读取响应体失败: %v\n", err) return } // 计算各个时间值(转成秒) connectTime := connectFinish.Sub(connectStart).Seconds() ttfb := firstResponseByte.Sub(requestStart).Seconds() totalTime := time.Since(requestStart).Seconds() // 输出结果 fmt.Printf("Connect时间: %.3f秒\nTTFB: %.3f秒\n总耗时: %.3f秒\n", connectTime, ttfb, totalTime) }
这个纯Go方案的优势:
- 不需要安装curl,代码可以直接在任何支持Go的平台运行
- 可以精准捕获更多细节时间(比如DNS解析时间、TLS握手时间等,只要扩展httptrace的钩子就行)
- 完全可控,比如可以自定义超时、代理、TLS配置等参数
内容的提问来源于stack exchange,提问作者Jagrati
相关产品推荐
相关产品推荐

