当前位置: 首页 > news >正文

go-文件缓存与锁

语言:golang

在抓取网站前,可能会多次读取文件中的cookie。频繁读取文件,性能不佳,故在go包中创建了一个map全局变量存储文件内容,只有键不存在时才去读取文件。
因为对go并不熟悉,才发现,不同请求读取到的是同一个变量(地址)。对于性能来说,这其实是好的。但出现一个问题:文件更新后,该变量的值依然是文件更新之前的内容,需要重新运行go包,而cookie随时可能失效而去更新,频繁重启这显然不现实。

解决方法
依旧采用map存储文件内容,但map的值为:1、文件的内容,2、文件的修改时间。
每次读取加读锁,并检查实际文件的修改时间,若与map中的值一致,则直接返回map中文件内容。
若不一致,则加写锁,再次检查修改时间,防止获取到写锁之前,文件已经修改。随后读取文件,获取文件中的内容,并更新内容和当前时间到map中。



type cacheEntry struct {
	content []string
	modTime time.Time
}

var (
	fileCache = make(map[string]cacheEntry)
	mu        sync.RWMutex
	group     singleflight.Group
)

func getFileModTime(path string) (time.Time, error) {
	fileInfo, err := os.Stat(path)
	if err != nil {
		return time.Time{}, err
	}

	return fileInfo.ModTime(), nil
}
func GetFile(file string) string {
	//合并请求
	result, err, _ := group.Do(file, func() (interface{}, error) {
		mu.RLock()
		entry, ok := fileCache[file]
		mu.RUnlock()
		path := GetFullPath(file)
		if ok {
			currentModTime, err := getFileModTime(path)
			if err != nil {
				return nil, err
			}
			if currentModTime.Equal(entry.modTime) {
				return entry.content, nil // 缓存有效
			}
		}
	
		mu.Lock()
		defer mu.Unlock()
	
		//再次检查,避免在获取到写锁的前一刻已经更新
		entry, ok = fileCache[file]
		if ok {
			currentModTime, err := getFileModTime(path)
			if err != nil {
				return nil, err
			}
			if currentModTime.Equal(entry.modTime) {
				return entry.content, nil // 缓存有效
			}
		}
	
		//读取文件并缓存
		content, err := os.ReadFile(path)
		if err != nil || len(content) == 0 {
			return nil, errors.New("文件不存在或为空")
		}
		//可选,按行分割内容
		lines := strings.Split(string(content), "\n")
		var branchContent []string
		for _, line := range lines {
			if line != "" {
				line = strings.TrimSpace(line)
				branchContent = append(branchContent, line)
			}
		}
	
		fileCache[file] = cacheEntry{
			content: branchContent,
			modTime: time.Now(),
		}
	
		return branchContent, nil
	})
}

相关文章:

  • stm32 晶振换算
  • 【蔚蓝星球的节日】世界海洋日的探索与海洋的重要性
  • 【Rust基础】Rust后端开发常用库
  • ssm框架整合
  • 芯科科技推出的BG29超小型低功耗蓝牙®无线SoC,是蓝牙应用的理想之选
  • 哈尔滨算力服务器托管推荐-青蛙云
  • 利用DeepSeek搭建跨工作表数据的可视化分析动态面板
  • VSCode 搭建C++编程环境 2025新版图文安装教程(100%搭建成功,VSCode安装+C++环境搭建+运行测试+背景图设置)
  • 智能三防手持终端破解传统仓储效率困局
  • 每天一道算法题【蓝桥杯】【两两交换链表中的节点】
  • 【SpringBoot】实现登录功能
  • ES 使用geo point 查询离目标地址最近的数据
  • Vue系统学习day01
  • idea中lombok插件的安装与使用
  • 接口自动化入门 —— JSON中的万能密码--JSONPath解析!
  • PyTorch 入门学习
  • 鸿蒙开发者社区资源的重要性
  • Smart Time Plus smarttimeplus-MySQLConnection SQL注入漏洞(CVE-2024-53544)
  • 快手__NS_sig3数据分析
  • c++介绍智能指针 十二(2)
  • 北师大发布《短视频家长指南》,回应短视频时代家庭教育挑战
  • 中国华能:1-4月新能源装机突破1亿千瓦,利润总额再创新高
  • 新华每日电讯:把纪律的螺丝拧得紧而又紧
  • 一女游客在稻城亚丁景区因高反去世,急救两个多小时未能恢复生命体征
  • 商务部:对原产于美国、欧盟、台湾地区和日本的进口共聚聚甲醛征收反倾销税
  • 国际博物馆日|在辽宁省博物馆遇见敦煌