在初始化期间建立Go中的常数
在我的Go程序中,有一些配置值我希望在程序执行期间保持不变,但我希望能够在部署站点进行更改。据我所知,使用在初始化期间建立Go中的常数,go,Go,在我的Go程序中,有一些配置值我希望在程序执行期间保持不变,但我希望能够在部署站点进行更改。据我所知,使用const关键字无法实现这一点,因为(同样,据我所知)它的值必须是编译时指定的常量。这意味着实现我想要的唯一方法是声明普通变量并在包的init函数中初始化它们。这并不是说这不起作用,而是说现在没有什么可以阻止这些伪常量的值发生变化 我的两个问题是: 我是否遗漏了const的工作原理 假设我不是,处理这个问题的首选方法是什么?一个公共函数,它返回一个我从未公开、从未更改过的私有变量?只是希望人
const
关键字无法实现这一点,因为(同样,据我所知)它的值必须是编译时指定的常量。这意味着实现我想要的唯一方法是声明普通变量并在包的init
函数中初始化它们。这并不是说这不起作用,而是说现在没有什么可以阻止这些伪常量的值发生变化
我的两个问题是:
const
的工作原理下面的代码与@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
}
您可以使用加载和保存配置文件 这是一个非常好的问题,因为它深入研究了我怀疑可能是Go-immutable状态的遗漏 从中可以看出,“常量表达式只能包含常量操作数,并在编译时求值。” 你不能使变量恒定,这是一种耻辱。Joe的回答建议将封装作为一种解决方案,这将很好地工作——但它冗长、乏味,并且可能会引入错误 相比之下,许多不纯函数语言将可变变量与单一赋值不可变值相结合。例如,Scala的关键字为“val”和“var”;Scala的“var”的含义与Go的“var”非常相似。不变性是工具箱中一个有用的工具,因为可以编写引用透明的无副作用函数,以及有状态的可变过程代码。两者都有各自的位置。不变性对于并发来说也是一个很有价值的工具,因为如果在goroutine之间共享不可变的值,就不必担心可能的竞争条件 因此,在我看来,在Go的众多优势中,这是Go的缺点之一。支持val和VAR可能并不难,区别在于编译器检查每个val是否只分配了一次
在添加该功能之前,封装是您唯一的选择。您可以执行以下操作:
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
这样,您就可以在编译时定义一个常量。创建一个文件“config.go”,并创建要公开的变量
不要导出它们(将它们全部小写)。而是创建公共(大写)func
s,以访问每个项目
package config
var x = 10
func X() int {
return x
}
当需要这些变量时,只需导入./config,并在代码中使用它们,如下所示:
if config.X()
显然,您可以在包
init
中设置变量,只需使用standard with。标准go标志允许通过传递命令行标志在程序启动时设置任意配置变量,而INIFALGS“神奇地”添加了对从ini文件读取配置变量的支持。您可以创建包含私有变量的类型(可从模块的init内部设置,但不能从外部设置)。然后将访问器funcs添加到类型中。这并不完全相同,但它是这样工作的。更好的方法是:创建一个文件“config.go”,创建要公开的变量,但不要导出它们(都是小写)。然后创建public(大写)func
s,用于访问每个项目。不需要类型,只需要一个模块。如果你回答@ChristopherPfohl,我会选择它。注意Go字符串在内部是不可变的。然而,保存字符串的变量本身是可变的,即使它保存的字符串是不可变的。这里有一个讨论:因为Go有指针,检查单个赋值不是不可能吗?不,不可能。检查单个赋值(注意,线索在名称中)和不变性之间有很大区别。像Scala这样的语言提供了这两种功能。你可以有一个而没有另一个,但两者兼顾似乎更有用。在我提到的论坛讨论中,有人提出了一个“不可变结构”,一旦完全初始化,该结构将变得不可变。这是个好主意。我认为单一赋值(“val”)也是一个很好的补充。它强调了Go+1中缺少的函数编程的一部分。这是一个有趣的想法。然而,除了有限的范围之外,没有什么可以阻止“a”被更改。所以它实际上不是一个常量,更多的是一个配置参数。虽然,由于straight Go缺少编译时参数,这在其他上下文中仍然有用。很好的调用,我最近在其他地方看到过这个成语,不记得在哪里了