我正在掌握Golang的做事方式。对于可能能够提供以下帮助的人,我非常感激不尽。首先是一些示例代码
package main
import (
"log"
"os"
)
func logIt(s string) {
f, _ := os.OpenFile("errors.log", os.O_RDWR|os.O_CREATE|os.O_APPEND,
0666)
defer f.Close()
log.SetOutput(f)
log.Println(s)
}
type iAm func(string)
func a(iam string) { logIt(iam + " A") }
func b(iam string) { logIt(iam + " B") }
func c(iam string) { logIt(iam + " C") }
var funcs = map[string]iAm{"A": a, "B": b, "C": c}
func main() {
funcs["A"]("Je suis")
funcs["B"]("Ich bin")
funcs["A"]("Yo soy")
funcs["D"]("Soy Yo")
}
说明
我是Go新手,所以我可能有我用过的其他语言的行李。在我看来,以先发制人的方式处理特殊情况(在使用之前检查密钥)既不聪明也不高效。正确?
答案 0 :(得分:8)
每次我想记录某些内容时,我都不会打开和关闭该文件。在启动时,我只打开它一次并将其设置为输出,并在程序存在之前关闭它。我不会使用logIt()
函数:只使用log
包的函数进行日志记录,这样您就可以进行格式化日志记录,例如与log.Printf()
等。
功能图完全没问题,并且性能良好。如果您需要更快的东西,可以根据函数名称执行switch
,并直接调用case
分支中的目标函数。
map
中的值是函数值。函数类型的零值为nil
,您无法调用nil
函数,因此必须在继续调用之前检查该值。请注意,如果使用不存在的键索引映射,则返回值类型的零值,如果是函数类型,则返回nil
。所以我们可以简单地检查值是否为nil
。还有另一个逗号成语,例如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
返回类型来表示是否找不到指定的函数。
您可以选择返回由例如{1}}创建的新error
值。 errors.New()
函数(因此它可以是动态的),或者您可以选择创建一个全局变量并具有固定的错误值,如:
var ErrInvalidFunc = errors.New("Invalid function!")
此解决方案的优点是call()
函数的调用者可以将返回的error
值与ErrInvalidFunc
全局变量的值进行比较,以了解情况和行为因此,例如:
if err := call("foo", "bar"); err != nil {
if err == ErrInvalidFunc {
// "foo" is an invalid function name
} else {
// Some other error
}
}
(略微压缩以避免垂直滚动条。)
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
}
}