-1

内置log且不log.Logger提供ErrorWarning类似Python.

Logger所以我想用下面的代码为内置类型写一个:

func (l *Logger) Error(v interface{}) {
    info := fmt.Sprintf("ERROR: %v", v)
    l.Println(info)
}

我将上面的代码morelog.go放在GOPATH/src/log.

main.go我写道:

logger := log.New(os.Stdout, "Test", 1)
logger.Error("Error in main.")

当我运行时go build,我得到:

./main.go:124: logger.Error undefined (type *log.Logger has no field or method Error)

我知道我可以通过定义一个新类型并在该类型上定义方法来实现类似的目标。但我认为如果我可以将方法直接添加到内置类型中会更好。

4

3 回答 3

5

这两个答案都是正确的,所以我将提供更多替代方案。您不能在未定义的类型上定义方法。函数确实是您可以做到这一点的一种方式,但您也可以通过重新定义类型或包装类型来做到这一点。

例如,如果您不关心拆分输出文件而只想修改日志行,那么您可以执行其中之一。

重新定义类型:

type MyLogger log.Logger

func (l MyLogger) Info(msg string, args ...interface{}) {
    log.Logger(l).Printf(msg, args...)
}

func (l MyLogger) Error(msg string, args ...interface{} {
    log.Logger(l).Printf("ERROR: " + msg, args...)
}

或包装类型:

type MyLogger struct {
  log.Logger
}

func (l MyLogger) Info(msg string, args ...interface{}) {
  l.Printf(msg, args...)
}

func (l MyLogger) Error(msg string, args ...interface{}) {
  l.Printf("ERROR: " + msg, args...)
}

重新定义类型会将您可以调用的方法集限制为您定义的方法集。如果不先进行转换,您将无法重用 *Printf 方法。通过嵌入来包装类型将允许您调用 *Printf 方法并用您自己的方法包装这些方法。您可以在每种情况下的 Info 和 Error 方法的实现中看到这方面的示例。

于 2013-01-02T19:24:28.590 回答
4

Rputikar 对您的基本问题的回答是正确的。您不能在不是您创建的类型上定义新方法。

那么,一种解决方案是不要挂在方法上,只需编写一个简单的函数。这是您想要编写为函数的方法。

Edit2:正如 Spirit Zhang 正确指出的那样,我的第一个版本的代码在 Lshortfile 或 Llongfile 标志的情况下丢失了行号。这是一个改进:

func LogError(l *log.Logger, v interface{}) {
    l.Output(2, fmt.Sprint("ERROR: ", v))
}

操场上的完整工作示例: http ://play.golang.org/p/MJaKQLt24L

如果你把这段代码放在 morelog.go 中,你可以把 morelog.go 放在你的主程序所在的目录下。或者不要为几个小功能使用单独的文件;只需将 LogError 和 LogWarning 代码与主程序放在同一个文件中即可。

编辑:默认记录器的示例:Edit2:此示例不适用于 Lshortfile 或 Llongfile。 我会把它留在这里,以便人们可以看到问题所在。我不知道编写这些函数以使用默认记录器的简单方法。

我的示例显示了适用于任何记录器的 LogError 函数。如果您只需要为默认记录器记录错误,那就更简单了:

func LogError(v interface{}) {
    log.Printf("ERROR: %v", v)
}

甚至,

func LogError(v interface{}) {
    log.Print("ERROR:", v)
}
于 2013-01-01T13:24:51.433 回答
2

您不能覆盖您未创建的类型的方法。同样,您不能在未创建的类型上定义新方法。

根据您的需要,您可以简单地拥有两个 log.Logger 实例,一个用于警告,一个用于错误。

http://play.golang.org/p/DQjIvk-wfI

package main

import (
    "log"
    "os"
)

func main() {

    errorLogger := log.New(os.Stderr, "ERROR: ", log.LstdFlags)
    warnLogger := log.New(os.Stdout, "WARNING: ", log.LstdFlags)

    errorLogger.Println("Hello, playground")
    warnLogger.Println("Hello, playground")
}
于 2013-01-01T10:00:42.260 回答