方便易用的全局函数

大多数时候,只不过是写一个简单的测试程序。例如:

package mainimport (    "log")func main(){
    log.Fatal("Come with fatal,exit with 1 \n")
}

这是Go语言标准log库的用法。

无须用logger := log.New(...)来产生一个指针。而且可以在程序的任何地方都能使用这个log。

阅读 log.go 源码:

...var std = New(os.Stderr, "", LstdFlags)
...// Fatal is equivalent to Print() followed by a call to os.Exit(1).func Fatal(v ...interface{}) {
    std.Output(2, fmt.Sprint(v...))
    os.Exit(1)
}

奥妙就在于 log.go 申请了一个全局变量 std,并封装了全局函数 log.Fatal。

log4go 的一个简单例子

这是 log4go 的一个简单例子:

package mainimport (    "time"
    log "github.com/ccpaging/log4go"
    "github.com/ccpaging/log4go/colorlog")func main() {
    log.AddFilter("stdout", log.DEBUG, colorlog.NewColorLogWriter())
    log.Debug("The time is now: %s", time.Now().Format("15:04:05 MST 2006/01/02"))
    log.Info("The time is now: %s", time.Now().Format("15:04:05 MST 2006/01/02"))
    log.Warn("The time is now: %s", time.Now().Format("15:04:05 MST 2006/01/02"))

    time.Sleep(200 * time.Millisecond)
}

效果如下图:

是不是很漂亮?运行环境:windows ConEmu。
colorlog 目前可以支持 Windows、Linux 以及 Cygwin 的 mintty 和 tmux

github.com/ccpaging/log4go/colorlog,这是一个彩色字符终端的log4go扩展插件。

喧宾夺主了……color term log 的话题以后再聊。

全局变量和全局函数

所以,log4go也有一个全局变量和一堆全局函数封装。详见:wrapper.go

var (
    Global Logger
)func init() {
    Global = Logger {        "stdout": NewFilter(DEBUG, NewConsoleLogWriter().SetFormat("%T %L %s %M")),
    }
}// Wrapper for (*Logger).AddFilterfunc AddFilter(name string, lvl Level, writer LogWriter) {
    Global.AddFilter(name, lvl, writer)
}

全局变量Global被自动初始化为一个 ConsoleLogWriter。它是黑白两色的字符终端。

// Add a new LogWriter to the Logger which will only log messages at lvl or// higher.  This function should not be called from multiple goroutines.// Returns the logger for chaining.func (log Logger) AddFilter(name string, lvl Level, writer LogWriter) Logger {    if filt, isExist := log[name]; isExist {
        filt.Close()        delete(log, name)
    }
    log[name] = NewFilter(lvl, writer)    return log
}

加入 ColorLogWriter 时,使用了同样的关键字 stdout
所以,原来的黑白终端输出被关闭,Global 中只保留了新的彩色终端。

如果 AddFilter 时,换一个关键字,例如 xxxout 会怎样?我不知道。
系统不会崩溃吧 :(

兼容标准log库

为了方便习惯于标准log库的程序员,封装了与标准库兼容的函数。
原来使用标准 log 库的程序只需换成 log4go 就可以用了?
想得美?!这是一个值得尝试的设想……

    func Fatal(v ...interface{})    func Fatalf(format string, v ...interface{})    func Fatalln(v ...interface{})    func Output(calldepth int, s string) error
    func Panic(v ...interface{})    func Panicf(format string, v ...interface{})    func Panicln(v ...interface{})    func Print(v ...interface{})    func Printf(format string, v ...interface{})    func Println(v ...interface{})

后续可能会加入:

    func Prefix() string
    func SetPrefix(prefix string)

这个功能也许在nanomsg的订阅模型中用到。

异步写日志的坑

细心的童鞋可能注意到测试程序中的一个特殊语句。

time.Sleep(200 * time.Millisecond)

纳尼?延时了200ms。我承认,这个问题令人困惑。如果没有这个延时,
可能在终端上什么也看不到。后果很严重……考试通不过,挂科……惨……

log4go 的每个日志都在一个 go routine 中运行。如果测试程序写的太简单了,
go routine 还没有来得及运行,主程序就退出了。

曾经设想在go routine中加 channel……然并没有什么用……

方便易用的全局函数

大多数时候,只不过是写一个简单的测试程序。例如:

package mainimport (    "log")func main(){
    log.Fatal("Come with fatal,exit with 1 \n")
}

这是Go语言标准log库的用法。

无须用logger := log.New(...)来产生一个指针。而且可以在程序的任何地方都能使用这个log。

阅读 log.go 源码:

...var std = New(os.Stderr, "", LstdFlags)
...// Fatal is equivalent to Print() followed by a call to os.Exit(1).func Fatal(v ...interface{}) {
    std.Output(2, fmt.Sprint(v...))
    os.Exit(1)
}

奥妙就在于 log.go 申请了一个全局变量 std,并封装了全局函数 log.Fatal。

log4go 的一个简单例子

这是 log4go 的一个简单例子:

package mainimport (    "time"
    log "github.com/ccpaging/log4go"
    "github.com/ccpaging/log4go/colorlog")func main() {
    log.AddFilter("stdout", log.DEBUG, colorlog.NewColorLogWriter())
    log.Debug("The time is now: %s", time.Now().Format("15:04:05 MST 2006/01/02"))
    log.Info("The time is now: %s", time.Now().Format("15:04:05 MST 2006/01/02"))
    log.Warn("The time is now: %s", time.Now().Format("15:04:05 MST 2006/01/02"))

    time.Sleep(200 * time.Millisecond)
}

效果如下图:

是不是很漂亮?运行环境:windows ConEmu。
colorlog 目前可以支持 Windows、Linux 以及 Cygwin 的 mintty 和 tmux

github.com/ccpaging/log4go/colorlog,这是一个彩色字符终端的log4go扩展插件。

喧宾夺主了……color term log 的话题以后再聊。

全局变量和全局函数

所以,log4go也有一个全局变量和一堆全局函数封装。详见:wrapper.go

var (
    Global Logger
)func init() {
    Global = Logger {        "stdout": NewFilter(DEBUG, NewConsoleLogWriter().SetFormat("%T %L %s %M")),
    }
}// Wrapper for (*Logger).AddFilterfunc AddFilter(name string, lvl Level, writer LogWriter) {
    Global.AddFilter(name, lvl, writer)
}

全局变量Global被自动初始化为一个 ConsoleLogWriter。它是黑白两色的字符终端。

// Add a new LogWriter to the Logger which will only log messages at lvl or// higher.  This function should not be called from multiple goroutines.// Returns the logger for chaining.func (log Logger) AddFilter(name string, lvl Level, writer LogWriter) Logger {    if filt, isExist := log[name]; isExist {
        filt.Close()        delete(log, name)
    }
    log[name] = NewFilter(lvl, writer)    return log
}

加入 ColorLogWriter 时,使用了同样的关键字 stdout
所以,原来的黑白终端输出被关闭,Global 中只保留了新的彩色终端。

如果 AddFilter 时,换一个关键字,例如 xxxout 会怎样?我不知道。
系统不会崩溃吧 :(

兼容标准log库

为了方便习惯于标准log库的程序员,封装了与标准库兼容的函数。
原来使用标准 log 库的程序只需换成 log4go 就可以用了?
想得美?!这是一个值得尝试的设想……

    func Fatal(v ...interface{})    func Fatalf(format string, v ...interface{})    func Fatalln(v ...interface{})    func Output(calldepth int, s string) error
    func Panic(v ...interface{})    func Panicf(format string, v ...interface{})    func Panicln(v ...interface{})    func Print(v ...interface{})    func Printf(format string, v ...interface{})    func Println(v ...interface{})

后续可能会加入:

    func Prefix() string
    func SetPrefix(prefix string)

这个功能也许在nanomsg的订阅模型中用到。

异步写日志的坑

细心的童鞋可能注意到测试程序中的一个特殊语句。

time.Sleep(200 * time.Millisecond)

纳尼?延时了200ms。我承认,这个问题令人困惑。如果没有这个延时,
可能在终端上什么也看不到。后果很严重……考试通不过,挂科……惨……

log4go 的每个日志都在一个 go routine 中运行。如果测试程序写的太简单了,
go routine 还没有来得及运行,主程序就退出了。

曾经设想在go routine中加 channel……然并没有什么用……

http://www.cnblogs.com/ccpaging/p/7218626.html