Golang在包之间共享配置

时间:2016-04-10 09:33:44

标签: go gorilla

所以我刚开始学习Go编程语言,并花了几个小时来查看示例,参考资料等等。大多数人都同意,没有比学习语言更好的方法而不是潜入并做出某些东西,这正是我此刻想要做的事情。我正在构建一个Restful Web服务。我已经设法运行基础知识以及插入数据库,注册路由等。但是在过去的两天里,我一直在努力实现应用程序配置/属性。可能只是因为我是新手,我的Go项目架构都是错误的,因此为什么我遇到这样的困难。没有进一步的到期,这是我的项目结构

src
   server
      database
         dbaccess.go
         dbcomm.go
      handling
         handler.go
         handlercomm.go
      models
         config.go
         response.go
         user.go
      routing
         routes.go
      main.go

这是我的config.go

package models

import (
   "io/ioutil"
   "encoding/json"
)

type Config struct  {
   Db map[string]string `json:"db"`
   Server map[string]string `json:"server"`
}


func NewConfig(fname string) *Config{
   data,err := ioutil.ReadFile(fname)
   if err != nil{
      panic(err)
   }
   config := Config{}
   err = json.Unmarshal(data,&config)
   if err != nil {
   panic(err)
}
return config

这是我的主要

func main(){
    args := os.Args[1:]
    if len(args) == 0{
       fmt.Println("********************\nMust specify a config file   in args\n********************")
    os.Exit(1)
   }

   config := models.NewConfig(args[0])
   port := config.Server["PORT"]

   router := routing.NewRouter()
   fmt.Printf(  "-------------------------------------------------\n"+
        "Listening and Serving on Port %s\n"+
        "-------------------------------------------------",port)

   log.Fatal(http.ListenAndServe(":"+port,router))
 }

最后这是我的路线被映射的地方

type Route struct {
   Name string
   Method string
   Pattern string
   HandlerFunc http.HandlerFunc
}

var routes = []Route{
   Route{
    "signup",
    "POST",
    "/signup",
    handling.PostSignUpUser,
   },

   Route{
    "authenticate",
    "POST",
    "/login",
    handling.PostLogin,
   },
}

func NewRouter() *mux.Router{
 router :=  mux.NewRouter().StrictSlash(true)
 for _,route := range routes{       
    router.Methods(route.Method)
          .Path(route.Pattern)
          .Name(route.Name)
          .Handler(route.HandlerFunc)
}

return router
}

因此,您可以在我的Main中看到我从一个文件初始化相关配置,这很好。但问题是如何在数据库包中使用main中的相同配置对象,因为我需要设置Host,Ports等?我可以再次解析文件,但我更愿意,如果我可以从一开始就共享那个对象。请指出我正确的方向

3 个答案:

答案 0 :(得分:2)

现在你想要的只是提供一个可以在另一个包中使用的变量,解决方法很简单,请记住,如果你声明一个以大写字母开头的变量名:[AZ],这个变量可以看到并用于go中的另一个包。

因此,您只需将config中的main.go重命名为Config并将其提取为全局变量:

var Config *models.Config
func main(){
args := os.Args[1:]
if len(args) == 0{
   fmt.Println("********************\nMust specify a config file   in args\n********************")
os.Exit(1)
}

Config = models.NewConfig(args[0])
port := Config.Server["PORT"]

router := routing.NewRouter()
fmt.Printf(  "-------------------------------------------------\n"+
    "Listening and Serving on Port %s\n"+
    "-------------------------------------------------",port)

log.Fatal(http.ListenAndServe(":"+port,router))
}

当你想在另一个包中使用它时,只需拨打<package name>.Config,包名是你的main.go所属的包名,在你的情况下可能是main

答案 1 :(得分:2)

我建议在config.go中声明一个全局变量,并使用init()函数对其进行初始化。这样,您就知道当任何包导入变量时,变量将始终被初始化。这是一些代码:

package models

import (
   "io/ioutil"
   "encoding/json"
)


var (

    Configuration Config 
)


init() {

    args := os.Args[1:]
    if len(args) == 0{
       fmt.Println("********************\nMust specify a config file   in args\n********************")
       os.Exit(1)
   }

   Configuration = NewConfig(args[0]) // configuration initialized here
}

type Config struct  {
   Db map[string]string `json:"db"`
   Server map[string]string `json:"server"`
}


func NewConfig(fname string) *Config{
   data,err := ioutil.ReadFile(fname)
   if err != nil{
      panic(err)
   }
   config := Config{}
   err = json.Unmarshal(data,&config)
   if err != nil {
      panic(err)
   }
   return config
}

var()将在init()之前运行,但init()将在导入它的包中的代码之前运行 。因此,如果main.go导入models包,则init()中的models将在main.go内的任何代码之前运行,因此变量Configuration将是在使用之前初始化。

Effective Go explanation of init()

答案 2 :(得分:0)

我为此专门构建了一个库,一个工具箱工厂(单个)和一个不可知的配置解析器(yaml,json和toml),让我们看看,看一下示例:SpareBox