在init期间建立Go中的常量

时间:2013-02-15 18:46:38

标签: go

在我的Go程序中,有一些配置值我希望在程序执行期间保持不变,但我希望能够在部署站点进行更改。据我所知,使用const关键字无法实现此目的,因为(据我所知),其值必须是编译时指定的常量 。这意味着实现我想要的唯一方法是声明正常变量并在包的init函数中初始化它们。并不是那不会起作用,而是现在没有什么可以防止这些伪常数的值发生变化。

我的两个问题是:

  1. 我是否遗漏了const的工作原理?
  2. 假设我不是,那么处理这个问题的首选方法是什么?一个公共函数,它返回一个我从未公开过的私有变量,从不改变它?只是希望人们不改变变量,因为它们确实是配置设置?

5 个答案:

答案 0 :(得分:3)

创建一个文件“config.go”并创建要公开的变种。

不要导出它们(使它们全部小写)。而是创建允许访问每个项目的公共(大写)func

package config

var x = 10

func X() int {
   return x
}

如果您想要这些变量,只需import ./config并在代码中使用它们,如下所示:

if config.X()

显然,您可以在包init中设置变量。

答案 1 :(得分:1)

以下代码与@Christopher的第二种方法几乎相同,只是它不是一个模块,它位于主包中。

package main

import (
    "os"
)

type Config struct {
    debug                bool
    key                  string
    proxyNumber          int
}

func (c *Config) Debug() bool {
    return c.debug
}
func (c *Config) Key() string {
    return c.key
}
func (c *Config) ProxyNumber() int {
    return c.proxyNumber
}

const (
    CONFIG_NAME = "config.ini"
)

var config *Config

func init() {
    DefaultConfig()
    if Exists(CONFIG_NAME) {
        //try to save the config file
    }else {
        //try to load from the config file

    }
}

func DefaultConfig() {
    config = &Config{debug:true, key:"abcde",
        proxyNumber:5,
    }
}

//Exist: check the file exist
func Exists(path string) bool {
    _, err := os.Stat(path)
    if err == nil { return true }
    if os.IsNotExist(err) { return false }
    return false
}

您可以使用config加载和保存配置文件。

答案 2 :(得分:1)

这是一个非常好的问题,因为它深入研究了我怀疑可能是Go-immutable状态的遗漏。

language reference开始,“常量表达式可能只包含常量操作数,并在编译时进行求值。”

你不能让变量不变,这是一种耻辱。 Joe的回答提出封装作为一种解决方案,它可以很好地工作 - 但它冗长,乏味并且可能会引入错误。

相比之下,许多不纯的函数语言将可变变量与单赋值不可变值组合在一起。例如,Scala有关键字'val'和'var'; Scala的'var'的含义与Go的'var'非常相似。不变性是工具箱中的一个有用工具,因为可以编写引用透明的无副作用函数,以及有状态可变过程代码。两者都有自己的位置。不可变性也是一种有价值的并发工具,因为如果在goroutine之间共享不可变值,就不用担心可能的竞争条件。

所以在我看来,在众多优势中,这是Go的缺点之一。它可能并不难以支持val和vars,不同之处在于编译器会检查每个val只分配一次。

在添加该功能之前,您已将封装作为唯一选项。

答案 3 :(得分:0)

您可以这样做:

package main

import (
    "fmt"
    "strconv"
)

var a string

func main() {
    myvar, err := strconv.Atoi(a)
    if err != nil {
        fmt.Println(err)
    }
    fmt.Println(myvar)
}

并使用

编译程序
go build -ldflags '-X main.a 10' test.go

这样你就可以在编译期间定义一个常量。

答案 4 :(得分:0)

只需将标准go flagsiniflags一起使用即可。标准go标志允许在程序启动时通过传递命令行标志来设置任意配置变量,而iniflags"神奇地"添加对从ini文件中读取配置变量的支持。