Contexthelper优化
2024-4-4
| 2024-4-7
0  |  阅读时长 0 分钟
Created time
Apr 3, 2024 06:52 AM
date
status
category
Origin
summary
tags
type
URL
icon
password
slug
本文由 简悦 SimpRead 转码, 原文地址 vlog.jiejaitt.top
有趣的技术实践分享

前言

TG bot 里面存了不少优化消息,有时间可以处理一下

contexthelper 优化需求

V3 版本优化——增加范型

阅读下面这段代码:
好的,这段代码是用 Go 语言写的,它定义了一个用于在context.Context中存储和加载值的 API。这个 API 允许你将多个值与一个给定的键关联,并且能够检索到这些值。这是通过使用一个结构体valuesMap来实现的,该结构体有一个读写互斥锁来保证并发访问的安全性。代码中定义了四个函数:StoreStoreSingleValueLoadLoadAll
Store函数允许你存储一个或多个值与一个键关联。StoreSingleValue是一个特化版本,它只存储单个值。Load函数用于获取与键关联的第一个值。LoadAll函数返回与键关联的所有值的切片。
每个函数都接受一个context.Context和一个键名作为参数,StoreStoreSingleValue还接受要存储的值。这些函数通过检查上下文中是否存在valuesMap来决定是否需要创建一个新的valuesMap。如果需要,它会创建一个新的valuesMap并将其与一个特殊的键contextKey关联在上下文中。
这个 API 可以用在需要在上下文中传递额外状态的场景中,特别是在处理并发请求时,每个请求都可以有自己的状态。

这里能不能改成 value... T 呢? func Store[T any](ctx context.Context, key string, value T) context.Context {}

在 Go 语言中,value... T表示一个变参函数,允许你传递零个或多个T类型的参数。在你提供的Store函数签名中,使用value... T是合理的,因为这样可以让你存储一个或多个与键相关联的值。实际上,代码中的Store函数已经使用了value... T来实现这一功能。
如果你想要改变StoreSingleValue函数来接受一个或多个值而不是单个值,你可以将其参数列表中的value T替换为value... T。不过,这样做之后,StoreSingleValue函数就和Store函数的功能一样了,因为它们都能接受一个或多个值。如果你的目的是要让StoreSingleValue函数有与Store函数不同的行为,例如只接受单个值,那么就不应该做这样的修改。
总结一下,如果你想要StoreSingleValue函数接受多个值,可以这样修改:
但请注意,这样修改后,StoreSingleValue的行为将与Store函数相同,你可能需要重新考虑函数的命名和用途,以避免混淆。

store 支持多个值的话那么应该增加单元测试吗?

是的,当你修改了Store函数以支持接受多个值,或者对任何函数进行了修改时,增加或更新单元测试是非常重要的。单元测试可以帮助你验证函数是否按照预期工作,并且在未来的代码更改中保证函数的行为仍然正确。
针对Store函数接受多个值的情况,你应该编写测试来确保以下几点:
  1. 函数能够正确接受并存储单个值。
  1. 函数能够正确接受并存储多个值。
  1. 当使用相同的键存储多个值时,这些值都应该被存储,并且能够通过LoadAll函数检索到。
  1. 验证并发安全性,确保在并发环境下Store函数能够正确工作。
这里是一个简单的单元测试示例,用于测试Store函数:
单元测试是确保你的代码质量的关键部分,尤其是在公共 API 或库中,你应该为所有公开的函数和方法提供彻底的测试。这样可以减少未来修改代码时引入错误的风险,并增强代码的可靠性。

如果没有加上 value...,那么就不能 ctx = Store(ctx, key, val2, val3) 吗?

如果没有在Store函数的参数中使用value... T,那么你就不能使用Store(ctx, key, val2, val3)这样的调用方式来传递多个值。在 Go 语言中,value... T表示该参数可以接收任意数量的T类型的值,这被称为变参函数。
如果Store函数的定义是这样的:
go
那么它只能接收一个T类型的值作为参数。这意味着你只能传递一个值给value参数,如下所示:
如果你尝试传递多个值,比如:
这将会导致编译错误,因为Store函数不是变参函数,它不接受多于一个的value参数。
如果你需要存储多个值,你必须要使用value... T这样的变参定义,或者你需要调用Store函数多次,每次传递一个值,像这样:
但请注意,这样的调用方式会根据你Store函数内部的实现,可能会覆盖之前存储的值,除非你的实现是将新值追加到现有列表中。所以,如果你想要一次性存储多个值,使用value... T是更好的选择。

返回 0 值 (t T),这样修改是的代码更加简洁

在 Go 语言中,返回类型的零值是一种常见的做法,尤其是在出错或者找不到值的情况下。零值是指一个变量在没有显式初始化时的默认值。例如,数值类型的零值是0,布尔类型的零值是false,指针类型的零值是nil,而对于切片、映射、通道、接口、函数等类型,零值也是nil
在你提供的Load函数中,如果在valuesMap中找不到对应的键,或者类型断言失败,函数会返回类型T的零值。这确实是一种简洁且有效的处理方式,因为它避免了在函数中多次重复编写创建零值变量的代码。
以下是Load函数的一个简化示例,其中返回类型T的零值:
在这个函数中,var zero T声明了一个类型为T的变量zero,其值是类型T的零值。如果上下文中没有找到值或类型断言失败,函数就会返回这个零值。
这种方式是 Go 语言常用的惯例,它使得代码简洁且易于理解,同时也避免了返回nil或者抛出异常,因为在 Go 中,通常是通过返回零值和错误值来处理异常情况。
大厂程序员都在用什么工具绘图?Handraw: 支持中文手写效果的 Excalidraw - 少数派免费的 MongoDB 云数据库 (MongoDB Atlas)使用教程
Loading...