go语言标准库expvar监控工具的实现

 更新时间:2026年04月22日 15:00:29   作者:虚拟之  
Go语言的expvar标准库是专为暴露程序内部指标设计的轻量级监控工具,支持通过HTTP接口以JSON格式实时查看运行状态,本文就来详细的介绍一下go语言标准库expvar监控工具的实现,感兴趣的可以了解一下

Go语言的expvar标准库是专为暴露程序内部指标设计的轻量级监控工具,支持通过HTTP接口以JSON格式实时查看运行状态。

一、基础功能说明

import "expvar"
  • 核心机制:内置/debug/vars端点,自动导出注册变量
  • 变量类型:支持Int/Float/String/Map/自定义类型
  • 线程安全:内置原子操作保证并发安全
  • 扩展能力:支持注册函数型变量

二、基础类型使用示例

1. 基础计数器

var counter = expvar.NewInt("requests")
func handler(w http.ResponseWriter, r *http.Request) {
    counter.Add(1)
    fmt.Fprintf(w, "Hello World")
}
func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}

测试命令:

curl http://localhost:8080/debug/vars | jq .requests

输出示例:

{ "requests": 158 }

2. 温度监控浮点数

temp := expvar.NewFloat("temperature")
temp.Set(26.5)
// 更新温度
temp.Add(0.5)

输出结果:

{ "temperature": 27.0 }

3. 版本信息字符串

version := expvar.NewString("version")
version.Set("v1.2.3")

输出展示:

{ "version": "v1.2.3" }

三、复合数据结构

4. Map结构统计

stats := expvar.NewMap("http")
stats.Set("requests", expvar.NewInt("total"))
stats.Set("errors", expvar.NewInt("count"))

stats.Get("requests").(*expvar.Int).Add(1)

输出结构:

{
  "http": {
    "requests": 42,
    "errors": 3
  }
}

5. 嵌套Map结构

dbStats := expvar.NewMap("database")
connStats := expvar.NewMap("connections")
dbStats.Set("mysql", connStats)
connStats.Set("open", expvar.NewInt("count"))
connStats.Set("max", expvar.NewInt("limit"))

输出结果:

{
  "database": {
    "mysql": {
      "open": 10,
      "max": 100
    }
  }
}

四、高级功能示例

6. 自定义结构体导出

type ServerStatus struct {
    Connections int
    mu          sync.Mutex
}
func (s *ServerStatus) String() string {
    s.mu.Lock()
    defer s.mu.Unlock()
    return fmt.Sprintf(`{"connections": %d}`, s.Connections)
}
status := &ServerStatus{}
expvar.Publish("server", status)
// 修改状态
status.mu.Lock()
status.Connections = 25
status.mu.Unlock()

输出结果:

{ "server": { "connections": 25 } }

7. 函数型变量

expvar.Publish("uptime", expvar.Func(func() interface{} {
    return time.Since(startTime).Seconds()
}))

动态输出:

{ "uptime": 3600.25 }

8. 原子计数器

var memStats expvar.Int
memStats.Set(1024)
go func() {
    for {
        atomic.AddInt64(&memStats.Value, 100)
        time.Sleep(time.Second)
    }
}()

持续增长的输出:

{ "memStats": 2024 }

五、系统级监控

9. 内存统计

expvar.Publish("memstats", expvar.Func(func() interface{} {
    var m runtime.MemStats
    runtime.ReadMemStats(&m)
    return m
}))

输出样例:

{
  "memstats": {
    "Alloc": 1024000,
    "TotalAlloc": 2048000,
    ...
  }
}

10. Goroutine计数

expvar.NewInt("goroutines").Set(int64(runtime.NumGoroutine()))

六、生产级应用

11. 动态配置中心

var config = expvar.NewMap("config")
config.Set("timeout", expvar.NewInt("seconds"))
config.Get("timeout").(*expvar.Int).Set(30)
// 动态修改配置
config.Get("timeout").(*expvar.Int).Set(60)

12. 实时QPS计算

var (
    totalRequests expvar.Int
    lastCheck     = time.Now()
)
expvar.Publish("qps", expvar.Func(func() interface{} {
    now := time.Now()
    interval := now.Sub(lastCheck).Seconds()
    qps := float64(totalRequests.Value()) / interval
    lastCheck = now
    totalRequests.Set(0)
    return qps
}))

13. 数据库连接池监控

dbConn := expvar.NewMap("db_connections")
dbConn.Set("open", expvar.NewInt("current"))
dbConn.Set("wait", expvar.NewInt("queued"))

// 连接获取时
dbConn.Get("open").(*expvar.Int).Add(1)
// 连接释放时
dbConn.Get("open").(*expvar.Int).Add(-1)

七、最佳实践建议

  1. 命名规范:使用service_metric的层级命名方式
  2. 性能考量:高频更新指标建议使用原子操作
  3. 安全防护:生产环境建议添加访问鉴权
  4. 数据聚合:结合Prometheus等工具进行可视化

八、完整示例程序

package main

import (
    "expvar"
    "fmt"
    "net/http"
    "runtime"
    "sync/atomic"
    "time"
)

func main() {
    // 基本计数器
    reqCounter := expvar.NewInt("http_requests")
  
    // 复合指标
    serviceStats := expvar.NewMap("service")
    serviceStats.Set("start_time", expvar.NewString(time.Now().Format(time.RFC3339)))
    serviceStats.Set("uptime", expvar.Func(func() interface{} {
        return time.Since(startTime).Seconds()
    }))

    // 自定义结构体
    type HealthStatus struct {
        Healthy bool `json:"healthy"`
    }
    expvar.Publish("health", expvar.Func(func() interface{} {
        return &HealthStatus{Healthy: true}
    }))

    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        reqCounter.Add(1)
        w.Write([]byte("OK"))
    })

    go func() {
        for {
            atomic.AddInt64(&reqCounter.Value, 1)
            time.Sleep(time.Second)
        }
    }()

    fmt.Println("Server running at :8080")
    http.ListenAndServe(":8080", nil)
}

该示例整合了多种expvar用法,通过以下命令查看完整指标:

curl http://localhost:8080/debug/vars | jq .

输出将包含:

{
  "http_requests": 42,
  "service": {
    "start_time": "2023-09-15T12:34:56Z",
    "uptime": 3600.25
  },
  "health": {
    "healthy": true
  }
}

到此这篇关于go语言标准库expvar监控工具的实现的文章就介绍到这了,更多相关go expvar内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • gin通过go build -tags实现json包切换及库分析

    gin通过go build -tags实现json包切换及库分析

    这篇文章主要为大家介绍了gin通过go build -tags实现json包切换及库分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • Go unsafe 包的使用详解

    Go unsafe 包的使用详解

    这篇文章主要介绍了Go unsafe 包的使用详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-01-01
  • Nunu快速构建高效可靠Go应用脚手架使用详解

    Nunu快速构建高效可靠Go应用脚手架使用详解

    这篇文章主要为大家介绍了如何使用Nunu快速构建高效可靠Go应用脚手架详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-06-06
  • Go通过不变性优化程序详解

    Go通过不变性优化程序详解

    这篇文章主要为大家介绍了Go通过不变性优化程序实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • Golang中的archive/zip包的常用函数详解

    Golang中的archive/zip包的常用函数详解

    Golang 中的 archive/zip 包用于处理 ZIP 格式的压缩文件,提供了一系列用于创建、读取和解压缩 ZIP 格式文件的函数和类型,下面小编就来和大家讲解下常用函数吧
    2023-08-08
  • GO语言的数组array与切片slice详解

    GO语言的数组array与切片slice详解

    这篇文章主要介绍了GO语言的数组array与切片slice,包括了GO语言数组定义赋值,GO语言多维数组,GO语言切片等知识点需要的朋友可以参考下
    2022-12-12
  • go语言中的template使用示例详解

    go语言中的template使用示例详解

    在Go语言中,可以通过text/template和html/template包来处理模板,本文提供了一个使用Go模板的基本示例,包括导入包、创建数据结构、定义模板、执行模板及运行程序,通过这些步骤,可以输出一个格式化的YAML配置
    2024-10-10
  • 从基础到高级全方位解析Go中反射的应用

    从基础到高级全方位解析Go中反射的应用

    本文我们将全面深入地探讨Go语言的反射机制,从反射的基础概念、为什么需要反射,到如何在Go中实现反射,以及在高级编程场景如泛型编程和插件架构中的应用,需要的可以参考下
    2023-10-10
  • Go异步任务解决方案之Asynq库详解

    Go异步任务解决方案之Asynq库详解

    需要在Go应用程序中异步处理任务? Asynq,简单高效的任务队列实现,下面这篇文章主要给大家介绍了关于Go异步任务解决方案之Asynq库的相关资料,需要的朋友可以参考下
    2023-02-02
  • go tool pprof 参数 '-base' 和 '-diff_base'之间的区别解析

    go tool pprof 参数 '-base' 和 '-diff_base&

    这篇文章主要介绍了go tool pprof 参数 '-base' 和 '-diff_base'之间的区别,两个参数都是用于计算当前 profile文件减去基准profile文件所获得的差值,用这个差值生成一个新的profile文件,本文给大家介绍的非常详细,需要的朋友可以参考下
    2023-05-05

最新评论