6

在我的 Go 程序中,有一些配置值我希望在程序执行期间保持不变,但我希望能够在部署站点进行更改。据我所知,没有办法用const关键字来实现这一点,因为(再次,据我所知)它的值必须是在compile time指定的常量。这意味着实现我想要的唯一方法是声明普通变量并在包的init函数期间初始化它们。并不是说这不起作用,而是现在没有任何东西可以阻止这些伪常数的值发生变化。

我的两个问题是:

  1. 我是否遗漏了一些关于如何const工作的东西?
  2. 假设我不是,处理这个问题的首选方法是什么?一个公共函数,它返回一个我从不公开、从不更改的私有变量?只是希望人们不要更改变量,因为它们实际上是配置设置?
4

6 回答 6

5

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

不要导出它们(使它们全部小写)。func而是创建可以访问每个项目的public (大写) s。

package config

var x = 10

func X() int {
   return x
}

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

if config.X()

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

于 2013-02-19T13:45:04.217 回答
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加载和保存配置文件。

于 2013-02-16T02:07:02.283 回答
1

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

语言参考中,“常量表达式可能只包含常量操作数并在编译时进行评估。”

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

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

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

在添加该功能之前,您只能选择封装。

于 2013-02-16T16:54:04.197 回答
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

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

于 2013-02-16T17:42:56.413 回答
0

只需使用带有iniflags的标准go 标志。标准的 go 标志允许在程序启动时通过传递命令行标志设置任意配置变量,而 iniflags “神奇地”添加了对从 ini 文件读取配置变量的支持。

于 2014-08-15T09:58:54.340 回答
0

您可以将变量包装在返回其值的函数中:

func genConst(x int) func() int {
    return func() int {
        return x
    }
}

var Constx = genConst(5)
var x1 = Constx()

这样,即使在定义它的文件中,也不会意外更改该值

于 2021-12-02T03:11:31.903 回答