В Go один из вариантов использование обобщенной структуры, в которой связываются остальные компоненты и модули. Для примера с собственного проекта пример обобщенной структуры
type Server struct {
sync.WaitGroup
Mux *chi.Mux
Log *log.Logger
LogFile *log.Logger
DB *gorm.DB
Render *render.Render
Convert *convert.Convert
Transliter *transliter.Transliter
Mailer *mailer.Mail
Flash *flash.Flash
Config *Config
StaticStock map[string]string //key = filesDir, []string = workDir
pool sync.Pool
Forms *forms.Form
Support *support.Support
LogReaders []LogReader
LogStock []string
LogFH *os.File
Paginator *paginate.Paginate
Gobdump *gobdump.Configdump
ConfigOrigin *Config
Uploader *uploader.Uploader
Datetime *Datetime
}
//иницализация для примера
func NewServer(originConfigUse bool) *Server {
//instance
s := new(Server)
//logger
s.Log = log.New(os.Stdout, SERVER, log.Ldate|log.Ltime|log.Lshortfile)
//gobdump
s.Gobdump = gobdump.NewConfigdump()
//config
cc := config.NewConf("config/dumpconfig.dmp", os.Stdout)
ci := new(Config)
if err := cc.ReadConfig("config/config.yaml", ci); err != nil {
s.Log.Fatal(err)
}
s.Config = ci
//assign config intance to SERVER
if originConfigUse == false {
s.ConfigOrigin = ci
s.Config = s.ConfigDumpRead(false)
}
//logfile
err := s.openLogs("logs")
if err != nil {
panic(err)
}
s.LogFile = log.New(s.LogFH, SERVER, log.Ldate|log.Ltime|log.Lshortfile)
//database
s.DatabaseConnect(ListTables)
//render
s.Render = render.NewRender(s.Config.TemplatePath, s.Config.TemplateDebug, s.Log, s.Config.TemplateDebugFatal)
//add user functions
s.Render.AddUserFilter("loop", s.Loop)
s.Render.AddUserFilter("loopstr", s.LoopStr)
s.Render.AddUserFilter("addstr", s.AddStr)
//s.Render.AddUserFilter("substr", s.SubStr)
//s.Render.AddUserFilter("intstr", s.IntToStr)
//transliter
s.Transliter = transliter.NewTransliter()
//mailer
s.Mailer = mailer.NewMail()
//flash
s.Flash = flash.NewFlash(s.Config.FlashSalt)
//converter
s.Convert = convert.NewConverter(s.Log)
//staticstock
s.StaticStock = make(map[string]string)
//chi router
s.Mux = chi.NewRouter()
//pool
s.pool = sync.Pool{}
s.pool.New = func() interface{} {
return &Data{
Server: s,
Flash: flash.NewFlash(s.Config.FlashSalt),
Stock: databox.NewData(),
}
}
//forms
s.Forms = forms.NewForm()
s.Forms.LoadFieldForms(formsdata)
//support
s.Support = support.NewSupport()
//добавление админа по умолчанию на основе данных из конфига
if err := s.addDefaultAdmin(); err != nil {
s.Log.Fatal(err)
}
//запуск горутин
s.Add(2)
go s.gorExpiredLogedUser(time.Minute * 60)
go s.gorPulicatePostLaterData(time.Minute * 2)
//paginator
pagparams := &paginate.Params{
Limit: s.Config.PaginateCountOnPage,
DBS: s.DB,
DebugQuery: s.Config.PaginateDebug,
SortTypes: s.Config.PaginateSortType,
CountLinks: s.Config.PaginateCountLinks,
}
s.Paginator = paginate.NewPaginate(pagparams)
//uploader
s.Uploader = uploader.NewUploader()
//datetime
s.Datetime = NewDateTimeList(2019)
//back result
return s
}
Привязка конфига идет к
ConfigOrigin *Config
Структура конфига + пакет для обработки его
package lib
import "time"
type Config struct {
//global
TemplatePath string `yaml:"templatepath"`
TemplateDebug bool `yaml:"templatedebug"`
TemplateDebugFatal bool `yaml:"teamplatedebugfatal"`
AdressHTTP string `yaml:"adresshttp"`
ReadTimeout time.Duration `yaml:"readtimeout"`
WriteTimeout time.Duration `yaml:"writetimeout"`
CertFile string `yaml:"certfile"`
KeyFile string `yaml:"keyfile"`
RedirectTrailingSlash bool `yaml:"redirecttrailingslash"`
RedirectFixedPath bool `yaml:"redirectfixedpath"`
Logfile string `yaml:"logfile"`
//roles
Roles []string `yaml:"roles"`
RolesAdmin []string `yaml:"rolesadmin"`
//database
DBTypeDB string `yaml:"dbtypedb"`
DBHost string `yaml:"dbhost"`
DBPort int `yaml:"dbport"`
DBUser string `yaml:"dbuser"`
DBPassword string `yaml:"dbpassword"`
DBDatabase string `yaml:"dbdatabase"`
DBSSLMode bool `yaml:"dbsslmode"`
DBSetMaxIdleConns int `yaml:"dbsetmaxidleconns"`
DBSetMaxOpenConns int `yaml:"dbsetmaxopenconns"`
DBSetConnMaxLifetime int `yaml:"dbsetconnmaxlifetime"`
//project
PaginateCountOnPage int `yaml:"paginatecountonpage"`
PaginateCountLinks int `yaml:"paginatecountlinks"`
PaginateSortType []string `yaml:"paginatesorttype"`
PaginateDebug bool `yaml:"paginatedebug"`
UploadPath string `yaml:"uploadpath"`
SitemapPath string `yaml:"sitemappath"`
SitemapHost string `yaml:"sitemaphost"`
HostFullPathHTTP string `yaml:"hostfullpathhttp"`
HostFullPathHTTPS string `yaml:"hostfullpathhttps"`
SeoTitle string `yaml:"seotitle"`
SeoDesc string `yaml:"seodesc"`
SeoKeys string `yaml:"seokeys"`
SeoRobot string `yaml:"seorobot"`
LaterPostTimePeriod int `yaml:"laterposttimeperiod"`
//session
MailTo string `yaml:"mailto"`
MailFrom string `yaml:"mailfrom"`
MailHost string `yaml:"mailhost"`
MailPort int `yaml:"mailport"`
MailUsername string `yaml:"mailusername"`
MailPassword string `yaml:"mailpassword"`
CSRFTimeActive int `yaml:"csrftimeactive"`
CSRFSalt string `yaml:"csrfsalt"`
CookieName string `yaml:"cookiename"`
CookieDomain string `yaml:"cookiedomain"`
CookieExpired int64 `yaml:"cookieexpired"`
CookieSalt string `yaml:"cookiesalt"`
RoleDefaultUser string `yaml:"roledefaultuser"`
SessionTime time.Duration `yaml:"sessiontime"`
SessionTimeExpired time.Duration `yaml:"sessiontimeexpired"`
SessionTimeSave time.Duration `yaml:"sessiontimesave"`
SessionPathSave string `yaml:"pathsavesession"`
TimerTime time.Duration `yaml:"timertime"`
SleepTimeCatcher time.Duration `yaml:"sleeptimecatcher"`
DeferPostSleepTime time.Duration `yaml:"deferpostsleeptime"`
DeferPostTime time.Duration `yaml:"deferposttime"`
ContactReview []string `yaml:"contactreview"`
FlashSalt string `yaml:"flashsatl"`
DefaultUserCookie string `yaml:"defaultusercookie"`
DefaultAdminEmail string `yaml:"defaultadminemail"`
DefaultAdminPassword string `yaml:"defaultadminpassword"`
DefaultAdminRole string `yaml:"defaultadminrole"`
RedisAdress string `yaml:"redisadress"`
RedisDB int `yaml:"redisdb"`
RedisPassword string `yaml:"redispassword"`
DumpConfigFile string `yaml:"dumpconfigfile"`
//oauth2 authorization
// +vk+
O2vkid string `yaml:"o2vkid"`
O2vkkey string `yaml:"o2vkkey"`
O2vkcallback string `yaml:"o2vkcallback"`
o2vkscope []string `yaml:"o2vkscope"`
// +yandex+
O2yandexid string `yaml:"o2yandexid"`
O2yandexkey string `yaml:"o2yandexkey"`
O2yandexcallback string `yaml:"o2yandexcallback"`
o2yandexscope []string `yaml:"o2yandexscope"`
// +google+
O2googleid string `yaml:"o2googleid"`
O2googlekey string `yaml:"o2googlekey"`
O2googlecallback string `yaml:"o2googlecallback"`
O2googlescope []string `yaml"o2googlescope"`
}
package config
import (
"os"
"log"
"io/ioutil"
"encoding/gob"
"github.com/go-yaml/yaml"
"io"
)
const (
logConfigPrefix = "[config-log] "
logConfigFlags = log.Ldate | log.Ltime | log.Lshortfile
msgsuccessReadDumpConfig = "дамп конфига успешно прочитан"
msgsuccessWriteDumpConfig = "дамп конфига успешно записан"
dumpfileflag = os.O_CREATE | os.O_RDWR | os.O_TRUNC
dumpfileperm = 0666
)
//---------------------------------------------------------------------------
// example other config
//---------------------------------------------------------------------------
type Conf struct {
Log *log.Logger
PathDumpconfig string
}
func (c *Conf) ReadConfig(fileConfig string, exConf interface{}) (error) {
//открываю файл конфигурации
f, err := os.Open(fileConfig)
if err != nil {
return err
}
//читаю файл конфига
b, err := ioutil.ReadAll(f)
if err != nil {
return err
}
//конвертирую его в структуру
err = yaml.Unmarshal(b, exConf)
if err != nil {
return err
}
return nil
}
func NewConf(pathDumpconfig string, logout io.Writer) *Conf {
n := &Conf{
PathDumpconfig: pathDumpconfig,
}
if logout == nil {
n.Log = log.New(os.Stdout, logConfigPrefix, logConfigFlags)
} else {
n.Log = log.New(logout, logConfigPrefix, logConfigFlags)
}
return n
}
//запись дампа конфигурационного файла
func (c *Conf) WriteDumpConfig(config interface{}) error {
f, err := os.OpenFile(c.PathDumpconfig, dumpfileflag, dumpfileperm)
if err != nil {
return err
}
defer f.Close()
enc := gob.NewEncoder(f)
err = enc.Encode(config)
if err != nil {
return err
}
if c.Log != nil {
c.Log.Printf(msgsuccessWriteDumpConfig)
return err
}
return nil
}
//читаем дамп конфигурационного файла
func (c *Conf) ReadDumpConfig(config interface{}) (error) {
f, err := os.Open(c.PathDumpconfig)
if err != nil {
return err
}
defer f.Close()
dec := gob.NewDecoder(f)
err = dec.Decode(config)
if err != nil {
return err
}
c.Log.Printf(msgsuccessReadDumpConfig)
return nil
}