N
N
NOONE2019-03-07 20:51:05
go
NOONE, 2019-03-07 20:51:05

How to initialize config for the whole project?

Hello, I have one question, there is a project with a lot of packages and go files, some of them have a data call from the config, a separate file is used to parse configs, how can I initialize the config so that I can use it in all project files?
I threw an example
-- Parsing the config

package controllers

import (
  "fmt"
  "io/ioutil"
  "log"
  "path/filepath"

  "gopkg.in/yaml.v2"
)

var config = "./conf.yml"

type Serverconfig struct {
  Port         string `yaml:"Port"`
  ReadTimeout  int    `yaml:"ReadTimeout"`
  WriteTimeout int    `yaml:"WriteTimeout"`
}

func (s *Serverconfig) validate() func() {
  fmt.Println("Parsing Config", config)
  return func() {
    if s.Port == "" {
      log.Fatal("Config Pars ERROR Port Required ", s.Port)
    }
    if s.ReadTimeout == 0 {
      log.Fatal("Config Pars ERROR ReadTimeout Requierd", s.ReadTimeout)
    }
    if s.WriteTimeout == 0 {
      log.Fatal("Config Pars ERROR WriteTimeout Requierd", s.WriteTimeout)
    }
  }
}

func Pars() *Serverconfig {
  config, error := filepath.Abs(config)
  if error != nil {
    log.Panic("ERROR: ", error)
  }
  yamlFile, error := ioutil.ReadFile(config)
  if error != nil {
    log.Panic("ERROR: ", error)
  }

  Serverconfig := Serverconfig{}
  error = yaml.Unmarshal(yamlFile, &Serverconfig)
  f := Serverconfig.validate()
  f()
  fmt.Println("Start server with parametrs\nServer Port" + Serverconfig.Port)
  if error != nil {
    log.Fatal(error)
  }
  return &Serverconfig

}

-- Main.GO
package main

import (
  "fmt"
  "gobots/route"
  "gowiki/controllers"
  "html/template"
  "log"
  "net/http"
  "time"
)

func main() {
  Serverconfig := controllers.Pars()
  handler := http.NewServeMux()
  handler.HandleFunc("/register/", register)
  s := http.Server{
    Addr:         Serverconfig.Port,
    Handler:      handler,
    ReadTimeout:  time.Duration(Serverconfig.ReadTimeout) * time.Second,
    WriteTimeout: time.Duration(Serverconfig.WriteTimeout) * time.Second,
  }
  log.Fatal(s.ListenAndServe())
}
func register(responseW http.ResponseWriter, request *http.Request) {
  if request.Method == "GET" {
    t, error := template.ParseFiles("templates/main.html")
    if error != nil {
      http.Error(responseW, error.Error(), 400)
      return
    }
    if err := t.Execute(responseW, nil); err != nil {
      fmt.Println(err)
      return
    }
  } else {
    route.Register(responseW, request)
    http.Redirect(responseW, request, "/home/", 302)
  }

}

here I initialize it in the main function and can use it accordingly only in the main function .., in other places the config becomes inaccessible, only if you do not call it as shown here,
ontrollers.Pars().MyVar
but this is somehow not correct and not beautiful, and it should not be like that , maybe there is already somewhere on the Internet the answer to my question, I tried to do it using init () but something did not work out

Answer the question

In order to leave comments, you need to log in

1 answer(s)
M
mr-spouk, 2019-03-12
@mr-spouk

In Go, one option is to use a generic structure where other components and modules are linked. For an example from my own project, an example of a generalized structure

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
}

Config binding goes to ConfigOrigin *Config Config
structure + package to process it
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
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question