Documentation
¶
Index ¶
- Constants
- func CacheKey(parts ...string) string
- func ColorByIndex(i int) (color.RGBA, bool)
- func ColorForSeed(seed string) color.RGBA
- func ETag(parts ...string) string
- func GetOrRender(key string, render func() ([]byte, error)) ([]byte, error)
- func GroupAvatarLines(text string) []string
- func GroupNameText(name string) string
- func GroupText(name string) string
- func IfNoneMatch(header, etag string) bool
- func IndividualText(nickname string) string
- func PaletteSize() int
- func Render(opts Options) ([]byte, error)
- func RenderGroup(text string, style GroupStyle, size int) ([]byte, error)
- func RenderIcon(style GroupStyle) ([]byte, error)
- func Renderable(s string) bool
- func SetDefaultCache(c *Cache)
- func VisibleRuneCount(s string) int
- type Cache
- type Config
- type GroupColorHex
- type GroupStyle
- type Hooks
- type Options
Constants ¶
const DefaultCacheSize = 4096
DefaultCacheSize 是未配置时的 LRU 容量(条目数)。
注意:LRU 按**条目数**而非字节计 bound。当前所有渲染输出都是 200×200 的简单 PNG (数 KB 量级),故 4096 条目 ≈ 十几 MB,足够覆盖活跃用户集。若将来有调用方(如 #478 群头像)缓存尺寸差异很大的图,常驻内存会随 entries×单图尺寸增长,届时应改为 按字节预算的缓存或下调容量(PR#481 评审)。
const (
// DefaultSize 是默认输出边长(与历史 generateDefaultAvatar 的 200 保持一致)。
DefaultSize = 200
)
Variables ¶
This section is empty.
Functions ¶
func CacheKey ¶ added in v1.7.0
CacheKey 从内容因子构造**单射**的共享缓存 key:长度分帧(<len>:<part>),保证不同 因子序列不会拼出同一个 key。所有头像端点(user/group/…)都应用本函数构造 GetOrRender 的 key,覆盖与各自 ETag 相同的因子。
注意:缓存 key **不能**用 ETag。ETag 是 32 位 CRC32 弱指纹,仅作 If-None-Match 验证符;作进程级共享缓存身份会碰撞 → 跨实体串图(且文字因子用户可控/可伪造)。
func ColorByIndex ¶ added in v1.7.0
ColorByIndex 返回色板第 i 个颜色(用户在二次弹窗显式选定的自定义色)。 i 越界时 ok=false,调用方应回退到 ColorForSeed。
func ColorForSeed ¶
ColorForSeed 按 seed 稳定地从色板选一个背景色。seed 用 uid(不随昵称变化), 保证同一用户在任何页面颜色一致、且改名后颜色不变。
func ETag ¶ added in v1.7.0
ETag 为服务端渲染的默认头像计算一个**弱 ETag**(W/ 前缀)。parts 应覆盖所有 决定图像内容的因子(渲染版本、seed→颜色、展示文字)——任一变化都会改变 ETag, 使共享缓存/浏览器在改名或换色后能 revalidate 拿到新图,而不是按 max-age 继续 返回旧图。这是弱验证符:指纹来自渲染输入而非响应字节,且渲染版本前缀已能在渲染 逻辑变更时使其失效;crc32 仅作轻量指纹(非安全用途)。
与 user 模块历史上的 avatarETag 行为一致;此处提升为共享实现供 group 等复用。
func GetOrRender ¶ added in v1.7.0
GetOrRender 用进程级共享缓存渲染 key 对应的头像;未设置默认缓存时直接渲染。 各端点 handler 应调用本函数,而不是各自持有 Cache。
func GroupAvatarLines ¶ added in v1.7.0
GroupAvatarLines 决定群默认头像文字的排版行,对齐设计稿「群组头像颜色枚举」:
- 含 CJK 等宽字符且 >= 3 字 → 两行,上少下多(floor/ceil 切分): "架构讨论"→["架构","讨论"](2+2)、"三个字"→["三","个字"](1+2);
- 纯拉丁/窄字符,或 <= 2 字 → 单行(设计稿 abcd/efgh/开发 均单行)。
func GroupNameText ¶ added in v1.7.1
GroupNameText derives a group's default-avatar text from its NAME: script-aware, leading 2 glyphs —— CJK(汉字/假名/谚文)前2 / 纯数字前2 / 纯拉丁等取首字母缩写 (≤2、大写) / 否则空(回退群组图标)。混排有 CJK 时只取 CJK(忽略拉丁/数字/符号)。
仅用于「群名自动取字」。用户显式设置的自定义头像文字走 GroupText(原样渲染、≤4), 不经过本规则。返回结果可能仍含本字体无字形的字符(罕见生僻字),调用方应配合 Renderable 判断,对不可渲染的结果回退到群组图标。
仅用于「改版前的存量老群(is_named=1)」的群名自动取字;新群(is_named=0)不调用本函数、 直接回退双人图标(见 modules/group writeGroupDefaultAvatar,2026-06-29 改版)。
func GroupText ¶ added in v1.7.0
GroupText 规范化用户**显式设置**的自定义群头像文字:取可见字符前 4(PRD:中/英文 最多 4 字符)。空白/控制/零宽字符在计数前剔除。
注意:本函数用于「自定义 avatar_text」的清洗(写入校验 + 渲染原样),**不是**群名 自动取字 —— 后者走 GroupNameText(script 感知、前2)。返回结果可能仍含本字体无字形 的字符,调用方应配合 Renderable 判断,对不可渲染的结果回退到群组图标。
func IfNoneMatch ¶ added in v1.7.0
IfNoneMatch 报告 If-None-Match 头是否匹配 etag(RFC 7232 §3.2 弱比较:忽略 W/ 前缀)。支持逗号分隔的多个验证符与通配 "*"。
func IndividualText ¶
IndividualText 返回个人默认头像应显示的文字:script 感知、**后** 2 字 —— CJK(汉字/假名/谚文)取后2(混排时只取 CJK)、纯数字后2、纯拉丁等取首字母缩写 (≤2、大写)、否则空(调用方回退 ASCII 兜底)。
个人取**后**两字(区别于群名 GroupNameText 取前2):中文昵称后缀(名)更具辨识度 (张三丰→三丰、王小明→小明,同钉钉/飞书)。空白/控制/零宽字符在计数前剔除。结果可能 含本字体无字形的字符(如 emoji),调用方应配合 Renderable 判断并回退。
func PaletteSize ¶ added in v1.7.0
func PaletteSize() int
PaletteSize 返回固定色板的颜色数,供调用方校验自定义色板下标的取值范围。
func Render ¶
Render 渲染一张「纯色圆 + 居中白色文字」的 PNG,返回编码后的字节。圆外**透明** (png.Encode 输出带 alpha 通道的 RGBA PNG),客户端在任意背景上合成时圆外不出白方块。 文字颜色固定为白色(与设计稿一致,不做对比度切换)。
func RenderGroup ¶ added in v1.7.0
func RenderGroup(text string, style GroupStyle, size int) ([]byte, error)
RenderGroup 渲染群默认头像「浅底描边圆 + 居中主题色文字」,圆外**透明**(输出带 alpha 通道的 RGBA PNG,客户端在任意背景上合成时圆外不出白方块),文字按 GroupAvatarLines 决定单行或两行(2×2)。个人头像继续走 Render(单行实心圆),本函数仅供群头像使用, 故可独立调整视觉而不影响个人头像。
func RenderIcon ¶ added in v1.7.0
func RenderIcon(style GroupStyle) ([]byte, error)
RenderIcon 渲染「浅底描边圆 + 双色群组图标」的 PNG,圆外**透明**,用于群名为空或 无法取字时的兜底。style 来自群头像专用色板,不影响个人头像 Render。
func Renderable ¶
Renderable 报告 s 非空且其中每个字符在内嵌字体里都有字形(非 .notdef)。 截出的昵称文字若含本字体无字形的字符(典型是 emoji),渲染会出豆腐块, 调用方应据此回退到其它兜底图。sfnt.Buffer 为局部变量,本函数并发安全。
func SetDefaultCache ¶ added in v1.7.0
func SetDefaultCache(c *Cache)
SetDefaultCache 设置进程级共享头像缓存(组合根在启动时调用一次)。
func VisibleRuneCount ¶ added in v1.7.0
VisibleRuneCount 返回 s 去除不可见字符后的可见 rune 数,供调用方校验自定义头像 文字长度(PRD:最多 4 个中文/英文字符)。
Types ¶
type Cache ¶ added in v1.7.0
type Cache struct {
// contains filtered or unexported fields
}
Cache 是带 singleflight 与渲染信号量的头像 bytes 缓存。零值不可用,须经 NewCache 构造; 方法对 nil 接收者安全(直接渲染,无缓存),便于在未配置缓存时退化。
func (*Cache) GetOrRender ¶ added in v1.7.0
GetOrRender 返回 key 对应的头像字节:命中 LRU 直接返回;否则经 singleflight 合并、 在渲染信号量约束下调用 render 生成一次,成功后写入 LRU。render 必须是确定性的 (相同 key → 相同字节),否则缓存会返回过期内容。
nil 接收者时直接调用 render(无缓存/合并/限流),用于缓存未配置的退化路径。
type Config ¶ added in v1.7.0
type Config struct {
// Size 是 LRU 最大条目数;<=0 用 DefaultCacheSize。
Size int
// MaxConcurrentRenders 是同时进行的真实渲染数上限(信号量容量);<=0 表示不限。
// 取值应 < GOMAXPROCS,给非头像流量留核;配合缓存后,渲染只在冷 key 时发生,
// 串行化冷渲染的代价是一次性的(之后命中缓存),换来洪峰下不饿死其它请求。
MaxConcurrentRenders int
// Hooks 是可观测性回调。
Hooks Hooks
}
Config 配置 Cache。
func ConfigFromEnv ¶ added in v1.7.0
func ConfigFromEnv() Config
ConfigFromEnv 从环境变量读取共享缓存配置(不含 Hooks —— 观测点由组合根注入, 以免本包依赖 pkg/metrics):
- DM_AVATAR_CACHE_SIZE: LRU 条目数,缺省/非法用 DefaultCacheSize;
- DM_AVATAR_RENDER_MAX_CONCURRENCY: 最大并发真实渲染数,缺省 max(1, GOMAXPROCS-1)。
type GroupColorHex ¶ added in v1.8.0
type GroupColorHex struct {
Index int // 色板下标 [0,PaletteSize),与 avatar_color 取值一致
Main string // 主题主色:圆描边 + 文字 + 图标前景人
Fill string // 圆填充浅色
IconBack string // 图标兜底(双人剪影)后景人浅色
}
GroupColorHex 是一档群头像配色的十六进制(#RRGGBB)形式,供**客户端本地渲染** (如「修改头像」实时预览、色圈选择)使用:客户端用 Index 选色、用 Main/Fill/IconBack 复刻服务端 PNG 的视觉(主色描边/文字、浅底圆、图标后景人),保证预览与建群/改群后 服务端渲染出的真图一致。
func PaletteHex ¶ added in v1.8.0
func PaletteHex() []GroupColorHex
PaletteHex 返回整套群头像色板的十六进制形式(按下标 0..PaletteSize 顺序),作为 色板的**唯一数据源**对客户端暴露——前端不再硬编码色值,避免与服务端 palette.go 漂移。
type GroupStyle ¶ added in v1.7.0
GroupStyle 是群默认头像的一套配色:Main 为主题主色(圆描边 + 文字 + 图标前景人), Fill 为圆填充浅色,IconBack 为图标后景人浅色。三者来自设计稿同一色组。
func GroupStyleByIndex ¶ added in v1.7.0
func GroupStyleByIndex(i int) (GroupStyle, bool)
GroupStyleByIndex 返回群主在二次弹窗显式选定的自定义色组。i 越界时 ok=false, 调用方应回退到 GroupStyleForSeed。取值范围与 ColorByIndex/PaletteSize 一致。
func GroupStyleForSeed ¶ added in v1.7.0
func GroupStyleForSeed(seed string) GroupStyle
GroupStyleForSeed 按 seed(群号)稳定地解出一套群头像配色。下标算法与 ColorForSeed **完全一致**(crc32 % len(palette)),故 Main 等于历史 ColorForSeed(seed) —— 保证 「改名不变色」「与旧派生色一致」,已合成/历史群切到新风格后主色不跳变。
type Hooks ¶ added in v1.7.0
type Hooks struct {
// OnHit / OnMiss:LRU 命中 / 未命中各记一次。
OnHit func()
OnMiss func()
OnShared func()
// OnRender:一次真实渲染完成,带耗时与错误(用于渲染延迟直方图)。
OnRender func(dur time.Duration, err error)
// OnSemaphoreWait:获取渲染信号量的等待耗时(>0 说明渲染并发已饱和、在排队)。
OnSemaphoreWait func(dur time.Duration)
// OnInflight:正在进行的渲染数变化(+1 开始 / -1 结束),用于 inflight gauge。
OnInflight func(delta float64)
}
Hooks 是可观测性回调,全部可选(nil 即 no-op)。刻意用函数字段而非接口,使本包 不依赖 pkg/metrics —— 由上层(modules/user)在构造时把 prometheus 观测点接进来。