从本地包共享对象

Jen*_*ton 0 go

我是Go的新手,我已经创建了一个按预期工作的应用程序。

我的应用程序结构如下:

myproj
   Gopkg.toml
   Gopkg.lock
   src
      server
         main.go
      utils
          file1.go
          logger.go
      handler
          handler1.go
          handler2.go
Run Code Online (Sandbox Code Playgroud)

现在在main.go文件中,我创建了一个如下记录器:

文件 server-> main.go

import (
      "handler"
      "utils"
      "github.com/sirupsen/logrus"
)

var logger                *logrus.Logger

fun init(){
    logger = utils.InitLogs()
} 


func main(){
  logger.info("my message")

  …

  handler.run()

} 
Run Code Online (Sandbox Code Playgroud)

一切工作按预期!

现在我想在handler1&2文件中使用记录器(来自本地项目中的diff包)

为此,我执行了以下步骤。在处理程序内init,记录器(与我在主文件中所做的完全一样)正在运行

文件 handler-> handler1.go

import (
      "utils"
      "github.com/sirupsen/logrus"
)

var logger                *logrus.Logger

fun init(){
   //Init the logger again
    logger = utils.InitLogs()
} 
func run(){
   //here Im not using logger otherwise maybe I can move it as parameter…
} 

func build(){
  //Here Im using the logger
  logger.info("Hi") 
}
Run Code Online (Sandbox Code Playgroud)

虽然这是工作,但我已经创建了2种记录仪的情况下,第一main第二handler1其中林不知道是最好的

我的问题是:

  1. 我想loggerhandler类/模块内部重用,是在Go中更好的方法吗?

这是diff包(在我的本地项目中),我不确定如果Im 不重复使用main方法中的相同logger对象,那么这是正确的方法...

  1. (较低的prio问题)我的项目结构可以使用Go吗?我用作为参考,类似... 有点不同

Edd*_* R. 5

如果要在整个项目中共享记录器实例,一种方法是按照Armin在其回答中的建议,将其作为utils包中的全局变量导出:

package utils

...

var Logger *logrus.Logger

func init() {
    Logger = InitLogs()
}
Run Code Online (Sandbox Code Playgroud)

我敢打赌,您可以将其InitLogs()更改为initLogs()

然后,在代码的其他位置,您可以导入utils并使用该记录器实例:

import "utils"

...
func something() {
    utils.Logger.Info("Hi")
}
Run Code Online (Sandbox Code Playgroud)

另外,如果将所有配置都放在一个地方有意义,则可以将记录器指针声明为config结构的字段,并将其与其余程序配置一起初始化(如果有的话)。

例如,假设您的utils包裹中包含以下物品:

package utils

...

type MyAppConfig struct {
    // whatever config parameters your app needs,
    // like DB connections, etc.
    Logger *logrus.Logger
}

// pass in whatever configuration parameters you need,
// like DB URL, etc.
func InitConfig() (*MyAppConfig, error) {
   // set up other configuration

   config := &MyAppConfig{
       // other config
       Logger: InitLogs(),
   }

   return config, nil
}

func (c *MyAppConfig) DoSomethingImportant() {
    c.Logger.Info("Hello")
}
Run Code Online (Sandbox Code Playgroud)

同时,您可以在其他任何地方使用它,例如在CLI界面中:

package main

import "utils"

...

func main() {
    // input, or CLI parameters...

    // pass in other CLI parameters, if any
    // (of course you'd have to change the function signature in
    // the previous file above)
    config, err := utils.NewConfig()
    if err != nil {
        // handle error
    }

    config.DoSomethingImportant()

    // or since Logger is exported:
    config.Logger.Info("hello")
}
Run Code Online (Sandbox Code Playgroud)

如果您发现需要进行很多全局配置(例如需要配置的Logger),则config结构是IMO更具扩展性的方法。另外,使用config类型可以使在单元测试中进行依赖注入比直接使用全局变量更容易。

另一方面,如果您只需要担心一个全局Logger,则config结构可能会过大,尤其是在设计测试时不需要使用该结构时。这是一个主观决定,具体取决于您的情况。

要回答第二个问题...

项目布局

如果/server有带有命令的主程序包,请将其移至下cmd/server

另外,按照您目前的方式,其他人依赖您的项目会有些混乱。由于您的存储库似乎始于src/,因此以下是其他人尝试导入您的utils软件包时的样子:

文件结构:

 <top of someone else's GOPATH>/
   src/
     myproject/src/utils/
       ...
Run Code Online (Sandbox Code Playgroud)

导入:

 import "myproject/src/utils"
Run Code Online (Sandbox Code Playgroud)

...实际上,由于您import "utils"现在在代码中,因此我认为您的代码不会在其他人的程序中编译,GOPATH因为他们没有$GOPATH/src/utils

解决方案:您的存储库不应包含src/。这个想法是,您设置了自己,$GOPATH然后在其中放入了不同的存储库/程序包。例如(假设您将代码托管在Github上):

 <top of gopath>/
   src/
     github.com/you/myproject/  <---- your repo starts here
       cmd/server/
         main.go
       utils
         file1.go
         logger.go
       handler
         handler1.go
         handler2.go
Run Code Online (Sandbox Code Playgroud)

这样可以使您的软件包对您和其他人都可以导入,如下所示:

import "github.com/you/myproject/utils"
Run Code Online (Sandbox Code Playgroud)

同样,此项目结构允许其他人将您的项目包含在$ GOPATH内或vendor/可互换地包含在内。