优化结构

This commit is contained in:
Yvan
2026-08-27 16:20:37 +08:00
parent 001e39da50
commit 653414a1da
54 changed files with 1257 additions and 3450 deletions
+80 -126
View File
@@ -5,6 +5,7 @@ import (
"fmt"
"os"
"path/filepath"
"slices"
"strings"
"sync"
"sync/atomic"
@@ -128,7 +129,7 @@ func (r *Store) UpdateDatabase(database *Database) {
if config.Data == nil {
config.Data = &Data{}
}
config.Data.Database = cloneDatabase(database)
config.Data.Database = clonePtr(database)
r.replace(config, false)
}
@@ -358,162 +359,115 @@ func decode(v *viper.Viper) (*Config, error) {
}
func setConfigPath(config *Config, path string) {
if config != nil && config.Admin != nil {
config.Admin.ConfigPath = path
if config == nil {
return
}
if config.Admin == nil {
config.Admin = &Admin{}
}
config.Admin.ConfigPath = path
}
// Every config type is plain data: scalars, pointers to structs, and slices of
// those. clonePtr and cloneSlice cover both shapes, so a clone function below is
// one line per pointer or slice field and nothing else. A field holding only
// scalars needs no line at all — the struct assignment already copied it.
func clonePtr[T any](value *T) *T {
if value == nil {
return nil
}
copied := *value
return &copied
}
func cloneSlice[T any](values []*T, clone func(*T) *T) []*T {
if values == nil {
return nil
}
copied := make([]*T, len(values))
for i, item := range values {
copied[i] = clone(item)
}
return copied
}
func cloneConfig(value *Config) *Config {
if value == nil {
return nil
}
// Viper's mapstructure output contains only value fields and pointers;
// round-tripping through a temporary map is unnecessarily lossy for
// durations. Explicit copy via YAML gives us a robust deep copy while
// preserving time.Duration values through the text hook.
copy := *value
if value.Server != nil {
server := *value.Server
copy.Server = &server
if value.Server.HTTP != nil {
http := *value.Server.HTTP
copy.Server.HTTP = &http
}
copied := *value
copied.Server = clonePtr(value.Server)
if copied.Server != nil {
copied.Server.HTTP = clonePtr(value.Server.HTTP)
}
if value.Data != nil {
data := *value.Data
copy.Data = &data
data.Database = cloneDatabase(value.Data.Database)
data.Redis = cloneRedis(value.Data.Redis)
data.Mongo = cloneMongo(value.Data.Mongo)
data.DatabaseList = make([]*Database, len(value.Data.DatabaseList))
for i, item := range value.Data.DatabaseList {
data.DatabaseList[i] = cloneDatabase(item)
}
data.RedisList = make([]*Redis, len(value.Data.RedisList))
for i, item := range value.Data.RedisList {
data.RedisList[i] = cloneRedis(item)
}
}
if value.Admin != nil {
copy.Admin = cloneAdmin(value.Admin)
}
return &copy
copied.Data = cloneData(value.Data)
copied.Admin = cloneAdmin(value.Admin)
return &copied
}
func cloneDatabase(value *Database) *Database {
func cloneData(value *Data) *Data {
if value == nil {
return nil
}
copy := *value
return &copy
copied := *value
copied.Database = clonePtr(value.Database)
copied.Redis = cloneRedis(value.Redis)
copied.Mongo = cloneMongo(value.Mongo)
copied.DatabaseList = cloneSlice(value.DatabaseList, clonePtr)
copied.RedisList = cloneSlice(value.RedisList, cloneRedis)
return &copied
}
func cloneRedis(value *Redis) *Redis {
if value == nil {
return nil
copied := clonePtr(value)
if copied != nil {
copied.ClusterAddrs = slices.Clone(value.ClusterAddrs)
}
copy := *value
copy.ClusterAddrs = append([]string(nil), value.ClusterAddrs...)
return &copy
return copied
}
func cloneMongo(value *Mongo) *Mongo {
if value == nil {
return nil
copied := clonePtr(value)
if copied != nil {
copied.Hosts = cloneSlice(value.Hosts, clonePtr)
}
copy := *value
copy.Hosts = make([]*MongoHost, len(value.Hosts))
for i, item := range value.Hosts {
if item != nil {
host := *item
copy.Hosts[i] = &host
}
}
return &copy
return copied
}
func cloneAdmin(value *Admin) *Admin {
if value == nil {
return nil
}
copy := *value
if value.JWT != nil {
item := *value.JWT
copy.JWT = &item
copied := *value
copied.JWT = clonePtr(value.JWT)
copied.Captcha = clonePtr(value.Captcha)
copied.Local = clonePtr(value.Local)
copied.Email = clonePtr(value.Email)
copied.Media = clonePtr(value.Media)
copied.System = clonePtr(value.System)
copied.App = clonePtr(value.App)
copied.DiskList = cloneSlice(value.DiskList, clonePtr)
copied.Storage = cloneStorage(value.Storage)
if copied.Zap = clonePtr(value.Zap); copied.Zap != nil {
copied.Zap.FileOnlyModules = slices.Clone(value.Zap.FileOnlyModules)
}
if value.Captcha != nil {
item := *value.Captcha
copy.Captcha = &item
if copied.CORS = clonePtr(value.CORS); copied.CORS != nil {
copied.CORS.Whitelist = cloneSlice(value.CORS.Whitelist, clonePtr)
}
if value.Local != nil {
item := *value.Local
copy.Local = &item
}
if value.Email != nil {
item := *value.Email
copy.Email = &item
}
if value.Media != nil {
item := *value.Media
copy.Media = &item
}
if value.System != nil {
item := *value.System
copy.System = &item
}
if value.Zap != nil {
item := *value.Zap
item.FileOnlyModules = append([]string(nil), value.Zap.FileOnlyModules...)
copy.Zap = &item
}
if value.App != nil {
item := *value.App
copy.App = &item
}
if value.CORS != nil {
item := *value.CORS
item.Whitelist = make([]*CORSRule, len(value.CORS.Whitelist))
for i, rule := range value.CORS.Whitelist {
if rule != nil {
next := *rule
item.Whitelist[i] = &next
}
}
copy.CORS = &item
}
if value.Storage != nil {
copy.Storage = cloneStorage(value.Storage)
}
copy.DiskList = make([]*Disk, len(value.DiskList))
for i, item := range value.DiskList {
if item != nil {
next := *item
copy.DiskList[i] = &next
}
}
return &copy
return &copied
}
func cloneStorage(value *Storage) *Storage {
if value == nil {
return nil
}
copy := *value
if value.Qiniu != nil {
item := *value.Qiniu
copy.Qiniu = &item
}
copy.AliyunOSS = cloneObjectStore(value.AliyunOSS)
copy.HuaweiOBS = cloneObjectStore(value.HuaweiOBS)
copy.TencentCOS = cloneObjectStore(value.TencentCOS)
copy.AWSS3 = cloneObjectStore(value.AWSS3)
copy.CloudflareR2 = cloneObjectStore(value.CloudflareR2)
copy.Minio = cloneObjectStore(value.Minio)
return &copy
}
func cloneObjectStore(value *ObjectStore) *ObjectStore {
if value == nil {
return nil
}
copy := *value
return &copy
copied := *value
copied.Qiniu = clonePtr(value.Qiniu)
copied.AliyunOSS = clonePtr(value.AliyunOSS)
copied.HuaweiOBS = clonePtr(value.HuaweiOBS)
copied.TencentCOS = clonePtr(value.TencentCOS)
copied.AWSS3 = clonePtr(value.AWSS3)
copied.CloudflareR2 = clonePtr(value.CloudflareR2)
copied.Minio = clonePtr(value.Minio)
return &copied
}