In my Go program, there are configuration values that I want to be constant for the duration of program execution, but that I want to be able to change at the deployment site. As far as I can tell, there's no way to achieve this with the const
keyword, since (again, as far as I can tell) its value must be a constant specified at compile time. This means that the only way to achieve what I want would be to declare normal variables and initialize them during the package's init
function. It's not that that won't work, but rather that there will now be nothing to prevent these pseudo-constant's values from changing.
My two questions are:
const
works?There can be any basic data type of constants like an integer constant, a floating constant, a character constant, or a string literal. How to declare: Constants are declared like variables but in using a const keyword as a prefix to declare a constant with a specific type. It cannot be declared using “=” syntax.
In Golang, all constants are untyped unless they are explicitly given a type at declaration. Untyped constants allow for flexibility. They can be assigned to any variable of compatible type or mixed into mathematical operations.
Untyped Constants They are not given a fixed type yet, like int32 or float64 or string , that would force them to obey Go's strict type rules. Note that, Although the value 1 is untyped, it is an untyped integer. So it can only be used where an integer is allowed.
An untyped constant has a default type which is the type to which the constant is implicitly converted in contexts where a typed value is required. For example default type for integer constant is int or it's float64 for floating-point number. In program V variable c is being set to untyped constant expression 1 .
Create a file "config.go" and create the vars you want to expose.
Don't export them (make them all lower case). Instead create public (upper case) func
s that give access to each item.
package config
var x = 10
func X() int {
return x
}
When you want those variables you simply import ./config
and use them in code as follows:
if config.X()
Obviously, you can set the variables in the package init
.
The following code is almost the same as the second method of @Christopher, except that it is not a module, it located in the main package.
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
}
you can use config to load and save the config file.
This is a very good question because it delves into what I suspect may be an omission from Go - immutable state.
From the language reference, "constant expressions may contain only constant operands and are evaluated at compile-time."
You cannot make vars constant, which is a shame. Joe's answer proposes encapsulation as a solution, which will work well - but it's verbose, tedious and might introduce errors.
By comparison, many impure functional languages combine mutable variables with single-assignment immutable values. For example, Scala has the keywords 'val' and 'var'; the meaning of Scala's 'var' is quite similar to Go's 'var'. Immutability is a useful tool in the toolbox because referentially-transparent side-effect-free functions can be written, alongside stateful mutable procedural code. Both have their place. Immutability is also an valuable tool for concurrency because there is no worry about possible race conditions if immutable values are shared between goroutines.
So in my opinion, amongst its many strengths, this is one of Go's shortcomings. It would presumably not be hard to support vals as well as vars, the difference being that the compiler checks that each val is assigned exactly once.
Until that feature is added, you have encapsulation as your only option.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With