【问题标题】:golang variable substitutiongolang 变量替换
【发布时间】:2018-08-02 10:24:04
【问题描述】:

如何在 go 中使用变量替换?

例如,我有以下代码:

debug_level := "Info"
log.Info("Debug Test")

我可以为日志函数使用变量 debug_level 来代替直接传递参数吗?比如:

debug_level := "Info"
log.${debug_level}("Debug Test")

谢谢。

【问题讨论】:

  • 您试图实现的是通过替换值或动态地将值传递给golang函数来动态创建函数名称。因为第一个是不可能的,虽然第二个可以。

标签: variables go logging substitution


【解决方案1】:

Go 是一种静态类型语言,如果你要通过名称调用函数或方法,编译器无法检查你提供的参数是否与函数的签名匹配。

改为使用函数变量:您当前保存方法或函数的变量name可以是函数类型的变量,保存函数方法值.

假设我们有以下日志功能:

func Info(args ...interface{}) {
    fmt.Print("[Info] ")
    fmt.Println(args...)
}

func Error(args ...interface{}) {
    fmt.Print("[Error] ")
    fmt.Println(args...)
}

你可以这样使用它:

var logger func(...interface{}) = Info

func main() {
    logger("something")
    logger = Error
    logger("Some other thing")
}

输出将是(在Go Playground 上尝试):

[Info] something
[Error] Some other thing

另请注意,这也适用于方法,而不仅仅是函数:

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...)
}

使用它:

var mainLogger = Logger{}

var logger func(...interface{}) = mainLogger.Info

func main() {
    logger("something")
    logger = mainLogger.Error
    logger("Some other thing")
}

输出(在Go Playground上试试):

[Info] something
[Error] Some other thing

查看相关问题:golang function alias on method receiver

【讨论】:

  • 这些可以用用户定义的函数来完成,如果我没记错的话,然后在里面调用像 log.Fatal 这样的预定义函数。我们不能使用预定义的函数来做到这一点,或者我们可以吗?
  • 我问的是 log.${debug_level} 是 OP 要求替换调用 golang 包 log.Fatallog.Println 的内容。我们也可以这样做吗?
  • 这个func (l Logger) Error(args ...interface{}) { fmt.Print("[Error] ") fmt.Println(args...) }是用户定义的函数,你可以在其中调用任何日志函数
  • @Himanshu 通过反射,可以通过名称调用方法。功能,你不能。 Details.
【解决方案2】:

Go 是一门静态语言,不仅它的所有变量(包括函数)都是静态类型的,而且所有函数都是静态编译和链接的。也就是说,如果没有任何准备,就无法根据函数名称动态调用函数。

这样做的方法包括像@icza 所提供的那样,使用可将名称映射到函数的映射,使用反射(至少目前仅限于方法),或使用插件和第 3 方加载器加载预编译的 Go 包。

从你的用例中我看到,使用地图是最简单的。

var logFn = map[string]func(...interface{}) {
    "Info": log.Info,
    "Debug": log.Debug,
}

顺便说一句,按照使用日志级别写日志真的没有意义。

示例:https://play.golang.org/p/drQzD1OH5ul

我想不出任何一种情况是您无法创建这样的地图,因为所有包在 Go 中都是静态链接的。

【讨论】:

  • 这与 OP 所问的不同,如果我对上下文有所了解。这不是替换,这只是将值分配给以函数作为值的映射,然后使用该映射的键调用该函数。这不是替代,我认为在 Golang 中是不可能的。至少对于函数来说不是,但对于字符串来说是这样。
  • 我认为这可以满足 OP 的需求。如果他真的想要那种替代,还有reflect,只要是一个类型的方法。
  • 是的,只有当它是 OP 真正想要的时候,它才能做 OP 想要的。你能告诉我们如何使用反射来实现它,它会有所帮助。
  • 那是用来返回值而不是替换值。反射不能动态修改函数名。 Golang 是静态类型语言。 OP 要求的内容适用于 PHP 等动态类型语言。您所做的是使用映射键替换了整个函数,而不是替换了包日志中的函数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-28
  • 2016-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多