写入日志文件
我不会每次要记录日志时都打开和关闭文件。在启动时,我只会打开一次并将其设置为输出,在程序退出之前关闭它。而且我不会使用logIt()
函数:只需使用log
包的函数记录日志,这样您可以使用格式化日志,例如使用log.Printf()
等。
动态函数选择
函数映射完全没问题,并且在性能方面表现良好。如果需要更快的速度,可以基于函数名称进行switch
,并在case
分支中直接调用目标函数。
检查键是否存在
map
中的值是函数值。函数类型的零值是nil
,您无法调用nil
函数,因此必须在继续调用之前检查该值。请注意,如果使用不存在的键索引映射,则返回值类型的零值,该类型为函数类型的情况下是nil
。因此,我们可以简单地检查该值是否为nil
。还有另一种逗号-OK惯用语,例如fv,ok:= funcs [name]
其中ok
将是一个布尔值,指示是否在映射中找到了键。
您可以在一个地方进行操作,不必在每次调用中重复它:
func call(name, iam string) {
if fv := funcs[name]; fv != nil {
fv(iam)
}
}
注意:
如果您选择使用 switch
,default
分支将处理无效的函数名称(在这种情况下,您当然不需要函数映射):
func call(name, iam string) error {
switch name {
case "A":
a(iam)
case "B":
b(iam)
case "C":
c(iam)
default:
return errors.New("Unknown function: " + name)
}
return nil
}
错误处理/报告
在 Go 语言中,函数可以有多个返回值,因此在 Go 中,通过返回一个 error
值来传播错误,即使该函数通常具有其他返回值。
因此,call()
函数应该具有一个 error
返回类型,以表明指定的函数是否无法找到。
您可以选择返回由例如 errors.New()
函数创建的新 error
值(因此它可以是动态的),或者您可以选择创建全局变量并具有固定的错误值,例如:
var ErrInvalidFunc = errors.New("Invalid function!")
这种解决方案的优点在于,call()
函数的调用者可以将返回的 error
值与全局变量 ErrInvalidFunc
的值进行比较,以知道情况并采取相应的行动,例如:
if err := call("foo", "bar"); err != nil {
if err == ErrInvalidFunc {
} else {
}
}
所以完整的修订程序如下:
(略微紧凑以避免出现垂直滚动条。)
package main
import ("errors"; "log"; "os")
type iAm func(string)
func a(iam string) { log.Println(iam + " A") }
func b(iam string) { log.Println(iam + " B") }
func c(iam string) { log.Println(iam + " C") }
var funcs = map[string]iAm{"A": a, "B": b, "C": c}
func main() {
f, err := os.OpenFile("errors.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
panic(err)
}
defer f.Close()
log.SetOutput(f)
call("A", "Je suis")
call("B", "Ich bin")
call("C", "Yo soy")
call("D", "Soy Yo")
}
func call(name, iam string) error {
if fv := funcs[name]; fv == nil {
return errors.New("Unknown funcion: " + name)
} else {
fv(iam)
return nil
}
}