The built-in log
and log.Logger
don't provide Error
or Warning
methods like Python
.
So I would like to write one for the built-in Logger
type with the following code:
func (l *Logger) Error(v interface{}) {
info := fmt.Sprintf("ERROR: %v", v)
l.Println(info)
}
And I put the code above in a file morelog.go
under GOPATH/src/log
.
And in the main.go
I wrote:
logger := log.New(os.Stdout, "Test", 1)
logger.Error("Error in main.")
When I run go build
, I get:
./main.go:124: logger.Error undefined (type *log.Logger has no field or method Error)
I know I can achieve the similar goal by defining a new type and define methods on that type. But I think it could be better if I can ad the method directly to the buit-in type.
Rputikar is correct on the answer to your basic question. You cannot define new methods on a type you didn't create.
One solution then, is to not get hung up on methods, just write a plain function. Here is the method you wanted written as a function.
Edit2: As Spirit Zhang correctly pointed out, my first version of this code lost the line number in the case of the Lshortfile or Llongfile flags. This is an improvement:
func LogError(l *log.Logger, v interface{}) {
l.Output(2, fmt.Sprint("ERROR: ", v))
}
Complete working example at playground: http://play.golang.org/p/MJaKQLt24L
If you put this code in morelog.go, you can put morelog.go in the directory with your main program. Or don't bother with a separate file for a couple of small functions; just put the LogError and LogWarning code right in the same file with your main program.
Edit: Example with default logger: Edit2: This Example does not work with Lshortfile or Llongfile. I'll leave it here so people can see the problem. I don't know of an easy way to write these functions to use the default logger.
My example shows a LogError function that works for any logger. If you just need to log errors for the default logger, it's even simpler:
func LogError(v interface{}) {
log.Printf("ERROR: %v", v)
}
or even,
func LogError(v interface{}) {
log.Print("ERROR:", v)
}
You can not override the method on a type you didn't create. Similarly you can not define new methods on a type you didn't create.
For your needs you can simply have two instances of log.Logger one for warning and one for error.
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")
}
Both of these answers are correct so I'll throw in a few more alternatives. You can't define methods on a type you didn't define. Functions are indeed one way you can do this but you can also do this by redefining the type or wrapping the type.
For instance if you don't care about splitting the outfile and just want to modify the log line then you can do one of these.
Redefine the type:
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...)
}
Or Wrap the type:
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...)
}
Redefining the type will limit the method set you can call on it to the ones you define. You won't be able to reuse the *Printf methods without casting it first. Wrapping the type by embedding it will allow you to call the *Printf methods and wrap those methods with your own. You can see examples of this in the implementations of the Info and Error methods for each case.