125 lines
3.3 KiB
Go
125 lines
3.3 KiB
Go
package log
|
||
|
||
import (
|
||
"reflect"
|
||
"sync"
|
||
)
|
||
|
||
// PoolManager 管理不同日志类型的对象池
|
||
type PoolManager struct {
|
||
pools sync.Map // map[reflect.Type]*sync.Pool
|
||
}
|
||
|
||
var (
|
||
globalPools = &PoolManager{}
|
||
resetCache sync.Map // map[reflect.Type]func(reflect.Value)
|
||
)
|
||
|
||
// GetEntry 从池中获取一个指定类型的日志对象,并确保其处于 Reset 后的干净状态
|
||
func GetEntry(t reflect.Type) any {
|
||
pool, _ := globalPools.pools.LoadOrStore(t, &sync.Pool{
|
||
New: func() any {
|
||
return reflect.New(t.Elem()).Interface()
|
||
},
|
||
})
|
||
entry := pool.(*sync.Pool).Get()
|
||
ResetLogEntry(entry) // 自动重置所有字段,无需子类实现 Reset
|
||
return entry
|
||
}
|
||
|
||
// 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) {
|
||
t := reflect.TypeOf(entry)
|
||
if pool, ok := globalPools.pools.Load(t); ok {
|
||
pool.(*sync.Pool).Put(entry)
|
||
}
|
||
}
|
||
|
||
// WithEntry 执行闭包并在结束后自动回收对象
|
||
func WithEntry(t reflect.Type, fn func(any)) {
|
||
entry := GetEntry(t)
|
||
defer PutEntry(entry)
|
||
fn(entry)
|
||
}
|
||
|
||
// LogEntry 是一个标记接口,用于识别是否为对象池管理的日志对象
|
||
type LogEntry interface {
|
||
IsLogEntry() bool
|
||
}
|