jjzjj

go - 从本地包中共享对象

coder 2023-07-02 原文

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

我的应用程序结构如下:

myproj
   Gopkg.toml
   Gopkg.lock
   src
      server
         main.go
      utils
          file1.go
          logger.go
      handler
          handler1.go
          handler2.go

现在在 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()

} 

一切都按预期工作!

现在我想在 handler1&2 文件中使用记录器(来 self 本地项目中的 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") 
}

虽然这是有效的,但我已经创建了记录器的两个实例,第一个main第二个handler1 上,我不确定哪个是最好的

My questions are:

  1. 我想在 handler 类/模块中重用 logger,在 Go 中有更好的方法吗?

这是差异包(在我的本地项目中),我不确定如果我不重新使用相同的记录器对象 main 方法,这是正确的方法...

  1. (低优先级问题)我的项目结构适合 Go 吗?我用了this作为类似的引用... also this这有点不同

最佳答案

如果你想在你的项目中共享你的记录器实例,一种方法是将它作为一个全局变量从你的 utils 包中导出,正如 Armin 在他的回答中所建议的那样:

package utils

...

var Logger *logrus.Logger

func init() {
    Logger = InitLogs()
}

我敢打赌,通过将 InitLogs() 更改为 initLogs()

,您可以不必导出 InitLogs()

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

import "utils"

...
func something() {
    utils.Logger.Info("Hi")
}

或者,如果将所有配置保存在一个地方有意义,您可以将记录器指针声明为配置结构的一个字段,并将其与程序配置的其余部分(如果有的话)一起初始化。

例如,假设您的 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")
}

与此同时,您可以在其他任何地方使用它,例如在您的 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")
}

如果你发现你最终需要配置很多全局的东西,比如你需要配置的 Logger,配置结构是更具可扩展性的 IMO 方法。作为一个额外的好处,使用配置类型比直接使用全局变量更容易在单元测试中进行依赖注入(inject)。

另一方面,如果您只需要担心一个全局记录器,那么配置结构可能就有点过分了,尤其是当您在设计测试时不需要检测它时。这是一个主观判断,具体取决于您的情况。

回答你的第二个问题......

项目布局

如果 /server 有一个带有命令的主包,将它移动到 cmd/server 下。

此外,以您目前的方式,依赖您的项目会让其他人感到困惑。由于您的存储库似乎从 src/ 开始,因此当其他人尝试导入您的 utils 包时,它看起来像这样:

文件结构:

 <top of someone else's GOPATH>/
   src/
     myproject/src/utils/
       ...

导入:

 import "myproject/src/utils"

... 实际上,由于您现在在代码中 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

这将使您的包对您和其他人来说是可导入的:

import "github.com/you/myproject/utils"

此外,此项目结构允许其他人将您的项目包含在他们的 $GOPATH 或他们的 vendor/ 中,可互换。

关于go - 从本地包中共享对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47737242/

有关go - 从本地包中共享对象的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. ruby-on-rails - 按天对 Mongoid 对象进行分组 - 2

    在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev

  3. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  4. ruby-on-rails - 如何验证非模型(甚至非对象)字段 - 2

    我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss

  5. Ruby 写入和读取对象到文件 - 2

    好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信

  6. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  7. ruby-on-rails - 未在 Ruby 中初始化的对象 - 2

    我在Rails工作并有以下类(class):classPlayer当我运行时bundleexecrailsconsole然后尝试:a=Player.new("me",5.0,"UCLA")我回来了:=>#我不知道为什么Player对象不会在这里初始化。关于可能导致此问题的操作/解释的任何建议?谢谢,马里奥格 最佳答案 havenoideawhythePlayerobjectwouldn'tbeinitializedhere它没有初始化很简单,因为你还没有初始化它!您已经覆盖了ActiveRecord::Base初始化方法,但您没有调

  8. ruby - 如何在 Rails 4 中使用表单对象之前的验证回调? - 2

    我有一个服务模型/表及其注册表。在表单中,我几乎拥有服务的所有字段,但我想在验证服务对象之前自动设置其中一些值。示例:--服务Controller#创建Action:defcreate@service=Service.new@service_form=ServiceFormObject.new(@service)@service_form.validate(params[:service_form_object])and@service_form.saverespond_with(@service_form,location:admin_services_path)end在验证@ser

  9. ruby - 是否可以覆盖 gemfile 进行本地开发? - 2

    我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI

  10. ruby - 一个 YAML 对象可以引用另一个吗? - 2

    我想让一个yaml对象引用另一个,如下所示:intro:"Hello,dearuser."registration:$introThanksforregistering!new_message:$introYouhaveanewmessage!上面的语法只是它如何工作的一个例子(这也是它在thiscpanmodule中的工作方式。)我正在使用标准的ruby​​yaml解析器。这可能吗? 最佳答案 一些yaml对象确实引用了其他对象:irb>require'yaml'#=>trueirb>str="hello"#=>"hello"ir

随机推荐