【问题标题】:Different const value for dev and prod env in gogo 中 dev 和 prod env 的不同 const 值
【发布时间】:2016-10-21 13:56:42
【问题描述】:

例如,我正在开发留言簿。它允许添加需要由版主批准的记录。但是在开发进一步的功能时,要批准在测试期间添加的每条记录是一件很痛苦的事情。 那么,是否可以构建应用程序的开发版本来创建具有适当标志集的此类记录?

例如 prod build 使用以下函数编译:

func NewRecord() Record {
    return Record{Moderation: Awaiting}
}

并且在 dev build 中编译为:

func NewRecord() Record {
    return Record{Moderation: Approved}
}

我知道在前端,当你构建一些 JS 应用程序时,在构建生产环境时设置 NODE_ENV=production 环境变量是一种常见的做法。 我在 Go 中寻找类似的东西。 我看到了两种方法,但都不喜欢其中任何一种:

  1. 我可以在开发时设置Awaiting = Approved,然后在构建产品版本时将其更改回实际值。但我担心有一天我会忘记这个模拟,将它提交给 repo 或类似的东西。
  2. 把函数改成类似

    func NewRecord() Record {
        if os.Getenv(mykey) == "production" {
                return Record{Moderation: Awaiting}
        } else {
                return Record{Moderation: Approved}
        }
    }
    

    但我不喜欢在运行时为每条新记录评估此条件。编译语言似乎是错误的。

如果这样的应用程序在构建为开发版本时可以显示警告(到 stdout/stderr),那就太好了。

谢谢。

【问题讨论】:

    标签: go


    【解决方案1】:

    我个人认为像您在示例中所做的那样使用环境变量是执行此操作的“正确”方法。这允许您在不重新构建应用程序的情况下调整行为,这在调试时可能非常有用。但是,如果您真的希望在编译时完成此操作,可以使用 build constraints 来完成。

    构建约束是放置在文件顶部的特殊注释,表示“仅在满足特定条件时构建此文件”。条件可以是我们正在构建的机器架构、我们正在运行的操作系统或用户在构建时指定的自定义构建标签。

    例如,您可以将函数调整为:

    func NewRecord() Record {
        return Record{Moderation: ModLevel}
    }
    

    然后定义 ModLevel 两次,一次在文件 modlevel_prod.go 中,看起来像这样(请注意,构建约束的语法正在改变,第二行是新语法,第一行不会有效更长时间。有关详细信息,请参阅本文末尾的链接):

    // +build !dev
    //go:build !dev
    
    package mypackage
    
    const ModLevel = Awaiting
    

    modlevel_dev.go 中的一个(或者在这种情况下文件名无关紧要)看起来像这样:

    // +build dev
    //go:build dev
    
    package mypackage
    
    const ModLevel = Approved
    

    现在,当你构建时,文件的生产版本是默认的,如果你想构建文件的开发版本,你必须明确地包含构建标签:

    $ go build -tags dev
    

    编辑:构建约束的语法正在改变。我已更新示例以包括旧版本和新版本(当前共存)。请参阅https://golang.org/issues/41184 了解更多信息以及弃用旧版本的时间表。

    【讨论】:

    • 谢谢!关于“正确性”,我还没有过时的意见。可能你是对的。
    • 虽然这个答案解决了上述问题,但我在这个问题上支持@mellow-marmot:这些东西应该保持可配置——也就是说,在启动时从某个配置文件和/或环境等。
    【解决方案2】:

    package initialization 处计算一次表达式:

    var defaultModeration int
    
    func init() {
        if os.Getenv(mykey) == "production" {
            defaultModeration = Awaiting
        } else {
            defaultModeration = Approved
        }
    }
    
    func NewRecord() Record { return Record{Moderation: defaultModeration} }
    

    【讨论】:

    • 谢谢。实际上,我会使用这种方法,但是标记的答案描述了如何在提出问题时实现我想要的。
    • 我唯一挑剔的评论是:不要对可变变量使用 init(永远)或包级别范围。这会回来咬你。在 main(或任何地方)初始化它并将其传递给需要它的东西。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-18
    • 1970-01-01
    • 1970-01-01
    • 2022-01-27
    • 1970-01-01
    • 2022-11-29
    相关资源
    最近更新 更多