2026-05-02 23:39:10 +08:00
|
|
|
|
package log
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"reflect"
|
|
|
|
|
|
"sync"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// PoolManager 管理不同日志类型的对象池
|
|
|
|
|
|
type PoolManager struct {
|
|
|
|
|
|
pools sync.Map // map[reflect.Type]*sync.Pool
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-04 09:57:29 +08:00
|
|
|
|
var (
|
|
|
|
|
|
globalPools = &PoolManager{}
|
|
|
|
|
|
resetCache sync.Map // map[reflect.Type]func(reflect.Value)
|
|
|
|
|
|
)
|
2026-05-02 23:39:10 +08:00
|
|
|
|
|
|
|
|
|
|
// GetEntry 从池中获取一个指定类型的日志对象,并确保其处于 Reset 后的干净状态
|
2026-05-04 09:57:29 +08:00
|
|
|
|
func GetEntry(t reflect.Type) any {
|
2026-05-02 23:39:10 +08:00
|
|
|
|
pool, _ := globalPools.pools.LoadOrStore(t, &sync.Pool{
|
|
|
|
|
|
New: func() any {
|
|
|
|
|
|
return reflect.New(t.Elem()).Interface()
|
|
|
|
|
|
},
|
|
|
|
|
|
})
|
2026-05-04 09:57:29 +08:00
|
|
|
|
entry := pool.(*sync.Pool).Get()
|
|
|
|
|
|
ResetLogEntry(entry) // 自动重置所有字段,无需子类实现 Reset
|
2026-05-02 23:39:10 +08:00
|
|
|
|
return entry
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-04 09:57:29 +08:00
|
|
|
|
// ResetLogEntry 使用反射自动化重置日志对象的所有字段
|
|
|
|
|
|
// 特别是对 Map 和 Slice 进行初始化(长度0,容量8)
|
|
|
|
|
|
func ResetLogEntry(v any) {
|
|
|
|
|
|
rv := reflect.ValueOf(v)
|
|
|
|
|
|
if rv.Kind() != reflect.Ptr || rv.IsNil() {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
t := rv.Type()
|
|
|
|
|
|
resetFunc, ok := resetCache.Load(t)
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
resetFunc = buildResetFunc(t.Elem())
|
|
|
|
|
|
resetCache.Store(t, resetFunc)
|
|
|
|
|
|
}
|
|
|
|
|
|
resetFunc.(func(reflect.Value))(rv.Elem())
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func buildResetFunc(t reflect.Type) func(reflect.Value) {
|
|
|
|
|
|
var funcs []func(reflect.Value)
|
|
|
|
|
|
for i := 0; i < t.NumField(); i++ {
|
|
|
|
|
|
field := t.Field(i)
|
|
|
|
|
|
fieldIdx := i
|
|
|
|
|
|
|
|
|
|
|
|
switch field.Type.Kind() {
|
|
|
|
|
|
case reflect.String:
|
|
|
|
|
|
funcs = append(funcs, func(rv reflect.Value) { rv.Field(fieldIdx).SetString("") })
|
|
|
|
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
|
|
|
|
funcs = append(funcs, func(rv reflect.Value) { rv.Field(fieldIdx).SetInt(0) })
|
|
|
|
|
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
|
|
|
|
|
funcs = append(funcs, func(rv reflect.Value) { rv.Field(fieldIdx).SetUint(0) })
|
|
|
|
|
|
case reflect.Float32, reflect.Float64:
|
|
|
|
|
|
funcs = append(funcs, func(rv reflect.Value) { rv.Field(fieldIdx).SetFloat(0) })
|
|
|
|
|
|
case reflect.Bool:
|
|
|
|
|
|
funcs = append(funcs, func(rv reflect.Value) { rv.Field(fieldIdx).SetBool(false) })
|
|
|
|
|
|
case reflect.Map:
|
|
|
|
|
|
funcs = append(funcs, func(rv reflect.Value) {
|
|
|
|
|
|
f := rv.Field(fieldIdx)
|
|
|
|
|
|
if f.IsNil() {
|
|
|
|
|
|
f.Set(reflect.MakeMapWithSize(f.Type(), 8))
|
|
|
|
|
|
} else {
|
|
|
|
|
|
f.Clear()
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
case reflect.Slice:
|
|
|
|
|
|
funcs = append(funcs, func(rv reflect.Value) {
|
|
|
|
|
|
f := rv.Field(fieldIdx)
|
|
|
|
|
|
if f.Cap() < 8 {
|
|
|
|
|
|
f.Set(reflect.MakeSlice(f.Type(), 0, 8))
|
|
|
|
|
|
} else {
|
|
|
|
|
|
f.SetLen(0)
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
case reflect.Struct:
|
|
|
|
|
|
subReset := buildResetFunc(field.Type)
|
|
|
|
|
|
funcs = append(funcs, func(rv reflect.Value) {
|
|
|
|
|
|
subReset(rv.Field(fieldIdx))
|
|
|
|
|
|
})
|
|
|
|
|
|
case reflect.Ptr, reflect.Interface:
|
|
|
|
|
|
zero := reflect.Zero(field.Type)
|
|
|
|
|
|
funcs = append(funcs, func(rv reflect.Value) {
|
|
|
|
|
|
rv.Field(fieldIdx).Set(zero)
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return func(rv reflect.Value) {
|
|
|
|
|
|
for _, f := range funcs {
|
|
|
|
|
|
f(rv)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func resetStruct(rv reflect.Value) {
|
|
|
|
|
|
// 已经不再直接调用,保留 buildResetFunc 逻辑即可
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// PutEntry 将日志对象归还到池中
|
|
|
|
|
|
func PutEntry(entry any) {
|
2026-05-02 23:39:10 +08:00
|
|
|
|
t := reflect.TypeOf(entry)
|
|
|
|
|
|
if pool, ok := globalPools.pools.Load(t); ok {
|
|
|
|
|
|
pool.(*sync.Pool).Put(entry)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// WithEntry 执行闭包并在结束后自动回收对象
|
2026-05-04 09:57:29 +08:00
|
|
|
|
func WithEntry(t reflect.Type, fn func(any)) {
|
2026-05-02 23:39:10 +08:00
|
|
|
|
entry := GetEntry(t)
|
|
|
|
|
|
defer PutEntry(entry)
|
|
|
|
|
|
fn(entry)
|
|
|
|
|
|
}
|
2026-05-04 09:57:29 +08:00
|
|
|
|
|
|
|
|
|
|
// LogEntry 是一个标记接口,用于识别是否为对象池管理的日志对象
|
|
|
|
|
|
type LogEntry interface {
|
|
|
|
|
|
IsLogEntry() bool
|
|
|
|
|
|
}
|