How can I use variable substitution in go?
For example, I have the following code:
debug_level := "Info"
log.Info("Debug Test")
Can I use a variable debug_level for the log function instead of passing a direct argument? Something like:
debug_level := "Info"
log.${debug_level}("Debug Test")
Thank you.
Go is a statically typed language, if you would call a function or method by name, the compiler could not check if the parameters you provide match the signature of the function.
Instead use function variables: your variable that currently holds the method or function name can be be a variable of function type, holding a function or method value.
Let's assume we have the following logging functions:
func Info(args ...interface{}) {
fmt.Print("[Info] ")
fmt.Println(args...)
}
func Error(args ...interface{}) {
fmt.Print("[Error] ")
fmt.Println(args...)
}
You may use it like this:
var logger func(...interface{}) = Info
func main() {
logger("something")
logger = Error
logger("Some other thing")
}
Output will be (try it on the Go Playground):
[Info] something
[Error] Some other thing
Also note that this works with methods too, not just with functions:
type Logger struct{}
func (l Logger) Info(args ...interface{}) {
fmt.Print("[Info] ")
fmt.Println(args...)
}
func (l Logger) Error(args ...interface{}) {
fmt.Print("[Error] ")
fmt.Println(args...)
}
Using it:
var mainLogger = Logger{}
var logger func(...interface{}) = mainLogger.Info
func main() {
logger("something")
logger = mainLogger.Error
logger("Some other thing")
}
Output (try it on the Go Playground):
[Info] something
[Error] Some other thing
See related question: golang function alias on method receiver
Go is a static language, not only all its variable, including functions, is statically typed, but also all functions are statically compiled and link. That said, it is not possible to calling a function dynamically according to its name without any preparation.
Methods of doing so including having a function viarable, as @icza provides, using a map that maps the name to the function, using reflect (limited to methods, at least for now), or using plugins and 3rd party loader to load pre-compiled Go packages.
From what I see from your use case, it is the simplest to use a map.
var logFn = map[string]func(...interface{}) {
"Info": log.Info,
"Debug": log.Debug,
}
By the way, it really does not make sense to write log according to using logging level.
Example: https://play.golang.org/p/drQzD1OH5ul
I cannot think of a single case that you cannot create such a map since all packages are statically linked in Go.