go构建高并发计数器

功能需求

  1. 计数器基本功能:支持递增、递减和获取当前计数值。
  2. 并发安全:确保多个协程同时访问计数器时不会出现数据竞争。
  3. 高效性能:使用适当的同步机制,优化性能。
  4. 重置功能:支持计数器重置为初始值。
  5. 持久化(可选) :支持将计数值持久化到文件或数据库中。
  6. 统计接口:提供API或方法获取计数器访问统计信息(如最大并发量)。

实施计划

  1. 技术调研 :对比 sync.Mutexsync.RWMutexsync/atomic 以及 sync.Map 的性能差异,选择最佳实现方式。
  2. 数据结构设计:定义计数器结构体,封装计数值和同步机制。
  3. 并发安全实现:采用选定的同步方案,完成增、减、获取操作。
  4. 压力测试:编写并发测试代码,验证线程安全性和性能。
  5. API接口封装:提供简单的对外接口,便于调用。
  6. 持久化实现(可选) :提供数据持久化接口(如JSON文件或SQLite数据库)。
  7. 统计接口实现:记录并发请求总数和最大并发量。
  8. 文档编写与代码整理:撰写代码使用文档及示例。

代码编写步骤

1. 数据结构设计

首先,定义一个计数器结构体,使用 sync/atomic 保证并发安全。

go 复制代码
go
複製編輯
package counter

import (
	"sync/atomic"
)

type Counter struct {
	value int64
}

func NewCounter() *Counter {
	return &Counter{}
}

2. 基本功能实现

提供递增、递减和获取当前值的方法。

scss 复制代码
go
複製編輯
// Increment 增加计数器值
func (c *Counter) Increment() {
	atomic.AddInt64(&c.value, 1)
}

// Decrement 减少计数器值
func (c *Counter) Decrement() {
	atomic.AddInt64(&c.value, -1)
}

// Get 获取当前计数器值
func (c *Counter) Get() int64 {
	return atomic.LoadInt64(&c.value)
}

3. 重置功能

增加一个重置方法。

scss 复制代码
go
複製編輯
// Reset 重置计数器
func (c *Counter) Reset() {
	atomic.StoreInt64(&c.value, 0)
}

4. 并发测试代码

编写测试代码,验证线程安全性。

go 复制代码
go
複製編輯
package main

import (
	"fmt"
	"sync"
	"counter"
)

func main() {
	c := counter.NewCounter()
	var wg sync.WaitGroup

	// 并发1000个协程进行递增
	for i := 0; i < 1000; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			c.Increment()
		}()
	}

	wg.Wait()
	fmt.Println("最终计数值:", c.Get())
}

5. 持久化(可选)

可以将计数器值写入文件。

go 复制代码
go
複製編輯
import (
	"os"
	"fmt"
)

func (c *Counter) SaveToFile(filename string) error {
	file, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer file.Close()

	_, err = file.WriteString(fmt.Sprintf("%d", c.Get()))
	return err
}

6. 统计接口(可选)

增加统计并发访问量。

go 复制代码
go
複製編輯
type CounterWithStats struct {
	Counter
	totalAccess int64
}

func (cs *CounterWithStats) Increment() {
	atomic.AddInt64(&cs.totalAccess, 1)
	cs.Counter.Increment()
}

func (cs *CounterWithStats) GetTotalAccess() int64 {
	return atomic.LoadInt64(&cs.totalAccess)
}

性能测试结果

可以使用 go test -bench 进行基准测试。

示例基准代码:

go 复制代码
go
複製編輯
package counter

import "testing"

func BenchmarkIncrement(b *testing.B) {
	c := NewCounter()
	for i := 0; i < b.N; i++ {
		c.Increment()
	}
}

总结

  1. 代码线程安全 ✅
  2. 支持高并发 ✅
  3. 性能较优(sync/atomicsync.Mutex 更快) ✅
  4. 可扩展功能:统计、持久化 ✅

收获

  1. atomic和sync.Mutex区别,atomic适合简单的原子计算,Mutex锁适合复杂的临界区操作
  2. go的结构体类继承的原理,和其他语言不一样,go的类继承其实是把其他结构体组合成了新的结构体
  3. benchmark测试的基础使用方法
相关推荐
HyggeBest4 小时前
Golang 并发原语 Sync Once
后端·go
zhuyasen1 天前
当Go框架拥有“大脑”,Sponge框架集成AI开发项目,从“手写”到一键“生成”业务逻辑代码
后端·go·ai编程
写代码的比利1 天前
Kratos 对接口进行加密转发处理的两个方法
go
chenqianghqu1 天前
goland编译过程加载dll路径时出现失败
go
马里嗷1 天前
Go 1.25 标准库更新
后端·go·github
郭京京1 天前
go语言redis中使用lua脚本
redis·go·lua
心月狐的流火号1 天前
分布式锁技术详解与Go语言实现
分布式·微服务·go
一个热爱生活的普通人1 天前
使用 Makefile 和 Docker 简化你的 Go 服务部署流程
后端·go