По-моему вы переусложняете без необходимости. Если значения из конфига только читаются, то потокобезопасность не нужна. Если же у вас предполагается еще и изменение, то в пул возвращаются указатели на "порченные" объекты, что тоже неправильно.
Если возможно, конфиг лучше прочитать в начале выполнения, а также паниковать на уровне main.
В результате и код проще, и тормозить нечему:
package config
import (
"encoding/json"
"fmt"
"os"
)
type Cfg struct {
// Fields
}
var (
cfg *Cfg
)
func Config() *Cfg {
return cfg
}
func LoadConfig() error {
f, err := os.Open("./config/config.json")
if err != nil {
return fmt.Errorf("can't open config file: %w", err)
}
defer f.Close()
dec := json.NewDecoder(f)
var c *Cfg
if err := dec.Decode(c); err != nil {
return fmt.Errorf("can't decode config file: %w", err)
}
if err := validate(c); err != nil {
return fmt.Errorf("can't validate config file: %w", err)
}
cfg = c
return nil
}
func validate(cfg *Cfg) error {
// Logic
return nil
}