【问题】
折腾:
中的:
的时候,遇到一个很诡异的问题:
log4go输出到console的信息不全,
而对应的输出到log文件中的信息是全的。
此处的一些背景是:
之前通过:
【已解决】go语言中实现log信息同时输出到文件和控制台(命令行)
中的:
【记录】go语言中通过log4go实现同时输出log信息到log文件和console
已经是可以正常,即全部的log的信息,包括后续得到的cookie的各种信息,一共3个cookie,和后续的信息,
都是可以正常的输出到console和log文件中的。
然后此处经过了一段时间的调试,即,先后运行了很多次。
【折腾过程】
1.开始以为是log4go的那个rotate导致的呢,但是发现自己的代码中,已经是对于log文件的话,没用rotate:
1 | gLogger.AddFilter( "log" , log4go.FINEST, log4go.NewFileLogWriter(logFilename, false )) |
2.然后又以为是返回的cookie值的某个域,是nil,然后可能会导致log打印输出为空呢。
但是通过注释掉对应的行,结果还是输出信息不全。
3.经过多次尝试,发现同样的代码的前提下,多次运行,每次输出截止到的地方都不同。
4.后来又经过一番调试,最后发现:
现象是:
虽然代码都是正常的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | /* * [File] * EmulateLoginBaidu.go * * [Function] * 【记录】用go语言实现模拟登陆百度 * * [Version] * 2013-09-19 * * [Contact] */ package main import ( "fmt" //"builtin" //"log" "os" "runtime" "path" "strings" //"io" "time" "io/ioutil" "net/http" //"net/http/cookiejar" //"sync" //"net/url" ) //import l4g "log4go.googlecode.com/hg" //import l4g "code.google.com/p/log4go" import "code.google.com/p/log4go" /*************************************************************************************************** Global Variables ***************************************************************************************************/ var gCurCookies []*http.Cookie; //var gLogger *log.Logger; var gLogger log4go.Logger; /*************************************************************************************************** Functions ***************************************************************************************************/ //do init before all others func initAll(){ gCurCookies = nil gLogger = nil initLogger() initCrifanLib() } //de-init for all func deinitAll(){ gCurCookies = nil if (nil == gLogger) { //gLogger.Close(); gLogger = nil } } //do some init for crifanLib func initCrifanLib(){ gLogger.Debug( "init for crifanLib" ) gCurCookies = nil return } //init for logger func initLogger(){ var filenameOnly string filenameOnly = GetCurFilename() var logFilename string = filenameOnly + ".log" ; //gLogger = log4go.NewLogger() //gLogger = make(log4go.Logger) //for console //gLogger.AddFilter("stdout", log4go.INFO, log4go.NewConsoleLogWriter()) //gLogger.AddFilter("stdout", log4go.INFO, log4go.NewConsoleLogWriter()) gLogger = log4go.NewDefaultLogger(log4go.INFO) //for log file if _, err := os.Stat(logFilename); err == nil { //fmt.Printf("found old log file %s, now remove it\n", logFilename) os.Remove(logFilename) } //gLogger.AddFilter("logfile", log4go.FINEST, log4go.NewFileLogWriter(logFilename, true)) //gLogger.AddFilter("logfile", log4go.FINEST, log4go.NewFileLogWriter(logFilename, false)) gLogger.AddFilter( "log" , log4go.FINEST, log4go.NewFileLogWriter(logFilename, false )) gLogger.Info( "Current time is : %s" , time.Now().Format( "15:04:05 MST 2006/01/02" )) return } // GetCurFilename // Get current file name, without suffix func GetCurFilename() string { _, fulleFilename, _, _ := runtime.Caller( 0 ) //fmt.Println(fulleFilename) var filenameWithSuffix string filenameWithSuffix = path.Base(fulleFilename) //fmt.Println("filenameWithSuffix=", filenameWithSuffix) var fileSuffix string fileSuffix = path.Ext(filenameWithSuffix) //fmt.Println("fileSuffix=", fileSuffix) var filenameOnly string filenameOnly = strings.TrimSuffix(filenameWithSuffix, fileSuffix) //fmt.Println("filenameOnly=", filenameOnly) return filenameOnly } //get url response html func GetUrlRespHtml(url string) string{ gLogger.Info( "GetUrlRespHtml, url=%s" , url) var respHtml string = "" ; resp, err := http.Get(url) gLogger.Info( "http.Get done" ) gLogger.Info( "resp.Header=%s" , resp.Header) gLogger.Info( "resp.Status=%s" , resp.Status) if err != nil { gLogger.Warn( "http get url=%s response error=%s\n" , url, err.Error()) } // defer resp.Body.Close() // gLogger.Info("defer resp.Body.Close done") body, errReadAll := ioutil.ReadAll(resp.Body) fmt.Println( "ioutil.ReadAll done" ) resp.Body.Close() fmt.Println( "resp.Body.Close done" ) gLogger.Info( "ioutil.ReadAll done" ) fmt.Println( "gLogger.Info done" ) if errReadAll != nil { gLogger.Warn( "ioutil.ReadAll for url=%s got error=%s\n" , url, errReadAll.Error()) } //gLogger.Debug("body=%s\n", body) gCurCookies = resp.Cookies() gLogger.Info( "resp.Cookies done" ) fmt.Println( "resp.Cookies done" ) respHtml = string(body) gLogger.Info( "resp body []byte to string done" ) //respHtml = "just for test log ok or not" return respHtml } func printCurCookies() { var cookieNum int = len(gCurCookies); gLogger.Info( "cookieNum=%d" , cookieNum) for i := 0 ; i < cookieNum; i++ { var curCk *http.Cookie = gCurCookies[i]; //gLogger.Info("curCk.Raw=%s", curCk.Raw) gLogger.Info( "------ Cookie [%d]------" , i) gLogger.Info( "Name\t=%s" , curCk.Name) gLogger.Info( "Value\t=%s" , curCk.Value) gLogger.Info( "Path\t=%s" , curCk.Path) gLogger.Info( "Domain\t=%s" , curCk.Domain) gLogger.Info( "Expires\t=%s" , curCk.Expires) gLogger.Info( "RawExpires=%s" , curCk.RawExpires) gLogger.Info( "MaxAge\t=%d" , curCk.MaxAge) gLogger.Info( "Secure\t=%t" , curCk.Secure) gLogger.Info( "HttpOnly=%t" , curCk.HttpOnly) gLogger.Info( "Raw\t=%s" , curCk.Raw) gLogger.Info( "Unparsed=%s" , curCk.Unparsed) } } func main() { initAll() gLogger.Info( "this is EmulateLoginBaidu.go" ) //step1: access baidu url to get cookie BAIDUID var baiduMainUrl string //baiduMainUrl := "http://www.baidu.com/"; //var baiduMainUrl string = "http://www.baidu.com/"; gLogger.Info( "baiduMainUrl=%s" , baiduMainUrl) respHtml := GetUrlRespHtml(baiduMainUrl) log4go.Debug( "respHtml=%s" , respHtml) //gLogger.Debug("respHtml=%s", respHtml) //printCurCookies() //gLogger.Error("why log can not show ????????") //var cookieNameListToCheck []string = ["BAIDUID"] //toCheckCookieNameList := [1]string{"BAIDUID"} toCheckCookieNameList := []string{ "BAIDUID" } toCheckCookieNum := len(toCheckCookieNameList) gLogger.Info( "toCheckCookieNum=%d\n" , toCheckCookieNum) //toCheckCookieNum=1 //fmt.Printf("toCheckCookieNum=%d\n", toCheckCookieNum) //toCheckCookieNum=1 for i := 0 ; i < toCheckCookieNum; i++ { cookieName := toCheckCookieNameList[i]; gLogger.Info( "[%d]cookieName=%s" , i, cookieName) //fmt.Printf("[%d]cookieName=%s\n", i, cookieName) //[0]cookieName=BAIDUID } deinitAll() } |
但是最终,只能输出到
resp.Cookies done
这一步,而后面的所有的信息,不论是info还是debug,不论是输出到console还是log文件,都是没了:
所以,很是奇怪。
至少,看起来,是log4go的bug。
无法正常输出log信息。
6.开始以为是:
1 | body, errReadAll := ioutil.ReadAll(resp.Body) |
的问题呢,结果上面代码证明了,也不是没有死在ReadAll,程序是可以正常运行下去的。
只是log4go有问题,无法输出而已。
7.所以,实在不行的话,搞得只能去重新使用旧的方法:
【记录】go语言中通过io的MultiWriter实现同时输出log信息到log文件和console
去实现输出log了。。。
虽然该法有缺点,但是估计应该会很稳定。
8.再继续去试试,看看能否找到根本原因,
到底是不是log4go的bug,还是其他问题。
9。也是看到了log4go中的:
func (ConsoleLogWriter) LogWritefunc (w ConsoleLogWriter) LogWrite(rec *LogRecord) This is the ConsoleLogWriter’s output method. This will block if the output buffer is full. |
感觉,或许真的是当前此处的log4go,内部是什么buffer满了。而导致无法继续输出了。
但是还是无法确定。
10.去试试,换个log文件,看看能否正常输出:
1 2 | //var logFilename string = filenameOnly + ".log"; var logFilename string = "log4go_debug_1.log" ; |
看看结果如何,结果问题依旧,看来和log文件无关。
11.而且,之前也遇到这样的诡异事情。
对于如下代码,是把抓取网页的部分,都注释掉了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 | /* * [File] * EmulateLoginBaidu.go * * [Function] * 【记录】用go语言实现模拟登陆百度 * * [Version] * 2013-09-19 * * [Contact] */ package main import ( //"fmt" //"builtin" //"log" "os" "runtime" "path" "strings" //"io" "time" //"io/ioutil" "net/http" //"net/http/cookiejar" //"sync" //"net/url" ) //import l4g "log4go.googlecode.com/hg" //import l4g "code.google.com/p/log4go" import "code.google.com/p/log4go" /*************************************************************************************************** Global Variables ***************************************************************************************************/ var gCurCookies []*http.Cookie; //var gLogger *log.Logger; var gLogger log4go.Logger; /*************************************************************************************************** Functions ***************************************************************************************************/ //do init before all others func initAll(){ gCurCookies = nil gLogger = nil initLogger() initCrifanLib() } //de-init for all func deinitAll(){ gCurCookies = nil if (nil == gLogger) { //gLogger.Close(); gLogger = nil } } //do some init for crifanLib func initCrifanLib(){ gLogger.Debug( "init for crifanLib" ) gCurCookies = nil return } //init for logger func initLogger(){ //var filenameOnly string //filenameOnly = GetCurFilename() //var logFilename string = filenameOnly + ".log"; var logFilename string = "log4go_debug_1.log" ; //gLogger = log4go.NewLogger() //gLogger = make(log4go.Logger) //for console //gLogger.AddFilter("stdout", log4go.INFO, log4go.NewConsoleLogWriter()) //gLogger.AddFilter("stdout", log4go.INFO, log4go.NewConsoleLogWriter()) gLogger = log4go.NewDefaultLogger(log4go.INFO) //for log file if _, err := os.Stat(logFilename); err == nil { //fmt.Printf("found old log file %s, now remove it\n", logFilename) os.Remove(logFilename) } //gLogger.AddFilter("logfile", log4go.FINEST, log4go.NewFileLogWriter(logFilename, true)) //gLogger.AddFilter("logfile", log4go.FINEST, log4go.NewFileLogWriter(logFilename, false)) gLogger.AddFilter( "log" , log4go.FINEST, log4go.NewFileLogWriter(logFilename, false )) gLogger.Info( "Current time is : %s" , time.Now().Format( "15:04:05 MST 2006/01/02" )) return } // GetCurFilename // Get current file name, without suffix func GetCurFilename() string { _, fulleFilename, _, _ := runtime.Caller( 0 ) //fmt.Println(fulleFilename) var filenameWithSuffix string filenameWithSuffix = path.Base(fulleFilename) //fmt.Println("filenameWithSuffix=", filenameWithSuffix) var fileSuffix string fileSuffix = path.Ext(filenameWithSuffix) //fmt.Println("fileSuffix=", fileSuffix) var filenameOnly string filenameOnly = strings.TrimSuffix(filenameWithSuffix, fileSuffix) //fmt.Println("filenameOnly=", filenameOnly) return filenameOnly } //get url response html func GetUrlRespHtml(url string) string{ gLogger.Info( "GetUrlRespHtml, url=%s" , url) var respHtml string = "" ; // resp, err := http.Get(url) // gLogger.Info("http.Get done") // gLogger.Info("resp.Header=%s", resp.Header) // gLogger.Info("resp.Status=%s", resp.Status) // if err != nil { // gLogger.Warn("http get url=%s response error=%s\n", url, err.Error()) // } // // defer resp.Body.Close() // // gLogger.Info("defer resp.Body.Close done") // //body, errReadAll := ioutil.ReadAll(resp.Body) // //body, _ := ioutil.ReadAll(resp.Body) // fmt.Println("ioutil.ReadAll done") // resp.Body.Close() // fmt.Println("resp.Body.Close done") // gLogger.Info("ioutil.ReadAll done") // fmt.Println("gLogger.Info done") // // if errReadAll != nil { // // gLogger.Warn("ioutil.ReadAll for url=%s got error=%s\n", url, errReadAll.Error()) // // } // //gLogger.Debug("body=%s\n", body) // gCurCookies = resp.Cookies() // gLogger.Info("resp.Cookies done") // fmt.Println("resp.Cookies done") respHtml = "just for test log ok or not" //respHtml = string(body) gLogger.Info( "resp body []byte to string done" ) return respHtml } func printCurCookies() { var cookieNum int = len(gCurCookies); gLogger.Info( "cookieNum=%d" , cookieNum) for i := 0 ; i < cookieNum; i++ { var curCk *http.Cookie = gCurCookies[i]; //gLogger.Info("curCk.Raw=%s", curCk.Raw) gLogger.Info( "------ Cookie [%d]------" , i) gLogger.Info( "Name\t=%s" , curCk.Name) gLogger.Info( "Value\t=%s" , curCk.Value) gLogger.Info( "Path\t=%s" , curCk.Path) gLogger.Info( "Domain\t=%s" , curCk.Domain) gLogger.Info( "Expires\t=%s" , curCk.Expires) gLogger.Info( "RawExpires=%s" , curCk.RawExpires) gLogger.Info( "MaxAge\t=%d" , curCk.MaxAge) gLogger.Info( "Secure\t=%t" , curCk.Secure) gLogger.Info( "HttpOnly=%t" , curCk.HttpOnly) gLogger.Info( "Raw\t=%s" , curCk.Raw) gLogger.Info( "Unparsed=%s" , curCk.Unparsed) } } func main() { initAll() gLogger.Info( "this is EmulateLoginBaidu.go" ) //step1: access baidu url to get cookie BAIDUID var baiduMainUrl string //baiduMainUrl := "http://www.baidu.com/"; //var baiduMainUrl string = "http://www.baidu.com/"; gLogger.Info( "baiduMainUrl=%s" , baiduMainUrl) respHtml := GetUrlRespHtml(baiduMainUrl) log4go.Debug( "respHtml=%s" , respHtml) //gLogger.Debug("respHtml=%s", respHtml) //printCurCookies() //gLogger.Error("why log can not show ????????") //var cookieNameListToCheck []string = ["BAIDUID"] //toCheckCookieNameList := [1]string{"BAIDUID"} toCheckCookieNameList := []string{ "BAIDUID" } toCheckCookieNum := len(toCheckCookieNameList) gLogger.Info( "toCheckCookieNum=%d\n" , toCheckCookieNum) //toCheckCookieNum=1 //fmt.Printf("toCheckCookieNum=%d\n", toCheckCookieNum) //toCheckCookieNum=1 for i := 0 ; i < toCheckCookieNum; i++ { cookieName := toCheckCookieNameList[i]; gLogger.Info( "[%d]cookieName=%s" , i, cookieName) //fmt.Printf("[%d]cookieName=%s\n", i, cookieName) //[0]cookieName=BAIDUID } deinitAll() } |
结果,竟然输出是:
console中,所有的打印信息,都没有了。。。
包括fmt的和log4go的。。。
全都是空的
而对应的log文件中,输出的是正的:
11.想办法,去删除log4go,再重新安装试试。
然后接着还是问题依旧:
1 2 3 | E:\Dev_Root\go\src\EmulateLoginBaidu>go run EmulateLoginBaidu.go E:\Dev_Root\go\src\EmulateLoginBaidu> |
12.此处,console和log文件:
log4go_debug_1.log
都是空的,都没有输出任何信息。
感觉像是:
要么是log4go,内部弄成死锁性质的,导致无法输出,或者是block掉了。
13.现在去试试:
只保留log4go中,初始化的console,去掉log文件的部分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | var logFilename string = "log4go_debug_1.log" ; //gLogger = log4go.NewLogger() //gLogger = make(log4go.Logger) //for console //gLogger.AddFilter("stdout", log4go.INFO, log4go.NewConsoleLogWriter()) //gLogger.AddFilter("stdout", log4go.INFO, log4go.NewConsoleLogWriter()) gLogger = log4go.NewDefaultLogger(log4go.INFO) //for log file if _, err := os.Stat(logFilename); err == nil { //fmt.Printf("found old log file %s, now remove it\n", logFilename) os.Remove(logFilename) } //gLogger.AddFilter("logfile", log4go.FINEST, log4go.NewFileLogWriter(logFilename, true)) //gLogger.AddFilter("logfile", log4go.FINEST, log4go.NewFileLogWriter(logFilename, false)) //gLogger.AddFilter("log", log4go.FINEST, log4go.NewFileLogWriter(logFilename, false)) gLogger.Info( "Current time is : %s" , time.Now().Format( "15:04:05 MST 2006/01/02" )) |
看看结果如何:
问题依旧。
此刻,的确没有创建什么log文件了。
并且还是之前的:console中也无输出了。
14.反过来:保留log文件,去掉console:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | var logFilename string = "log4go_debug_1.log" ; //gLogger = log4go.NewLogger() gLogger = make(log4go.Logger) //for console //gLogger.AddFilter("stdout", log4go.INFO, log4go.NewConsoleLogWriter()) //gLogger.AddFilter("stdout", log4go.INFO, log4go.NewConsoleLogWriter()) //gLogger = log4go.NewDefaultLogger(log4go.INFO) //for log file if _, err := os.Stat(logFilename); err == nil { //fmt.Printf("found old log file %s, now remove it\n", logFilename) os.Remove(logFilename) } //gLogger.AddFilter("logfile", log4go.FINEST, log4go.NewFileLogWriter(logFilename, true)) //gLogger.AddFilter("logfile", log4go.FINEST, log4go.NewFileLogWriter(logFilename, false)) gLogger.AddFilter( "log" , log4go.FINEST, log4go.NewFileLogWriter(logFilename, false )) gLogger.Info( "Current time is : %s" , time.Now().Format( "15:04:05 MST 2006/01/02" )) |
看看结果如何:
结果是log文件:log4go_debug_1.log
虽然被创建了。
结果还是空的。
console中,自然还是没有输出。
15。看到:
Re: [go-nuts] log4go flush – msg#01802
这人,遇到和我,有点点类似的问题:
其要输出的hello world,由于程序的exit,导致无法输出了:正常的话,肯定是应该可以的。
那我此处,去试试,加上exit,看看什么效果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | //init for logger func initLogger(){ //var filenameOnly string //filenameOnly = GetCurFilename() //var logFilename string = filenameOnly + ".log"; var logFilename string = "log4go_debug_1.log" ; //gLogger = log4go.NewLogger() gLogger = make(log4go.Logger) //for console //gLogger.AddFilter("stdout", log4go.INFO, log4go.NewConsoleLogWriter()) //gLogger.AddFilter("stdout", log4go.INFO, log4go.NewConsoleLogWriter()) //gLogger = log4go.NewDefaultLogger(log4go.INFO) //for log file if _, err := os.Stat(logFilename); err == nil { //fmt.Printf("found old log file %s, now remove it\n", logFilename) os.Remove(logFilename) } //gLogger.AddFilter("logfile", log4go.FINEST, log4go.NewFileLogWriter(logFilename, true)) //gLogger.AddFilter("logfile", log4go.FINEST, log4go.NewFileLogWriter(logFilename, false)) gLogger.AddFilter( "log" , log4go.FINEST, log4go.NewFileLogWriter(logFilename, false )) gLogger.Info( "Current time is : %s" , time.Now().Format( "15:04:05 MST 2006/01/02" )) exit(); return } |
结果是:
根本没exit函数:
1 | .\EmulateLoginBaidu.go:97: undefined: exit |
16.换成log4go的close试试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | //init for logger func initLogger(){ //var filenameOnly string //filenameOnly = GetCurFilename() //var logFilename string = filenameOnly + ".log"; var logFilename string = "log4go_debug_1.log" ; //gLogger = log4go.NewLogger() gLogger = make(log4go.Logger) //for console //gLogger.AddFilter("stdout", log4go.INFO, log4go.NewConsoleLogWriter()) //gLogger.AddFilter("stdout", log4go.INFO, log4go.NewConsoleLogWriter()) //gLogger = log4go.NewDefaultLogger(log4go.INFO) //for log file if _, err := os.Stat(logFilename); err == nil { //fmt.Printf("found old log file %s, now remove it\n", logFilename) os.Remove(logFilename) } //gLogger.AddFilter("logfile", log4go.FINEST, log4go.NewFileLogWriter(logFilename, true)) //gLogger.AddFilter("logfile", log4go.FINEST, log4go.NewFileLogWriter(logFilename, false)) gLogger.AddFilter( "log" , log4go.FINEST, log4go.NewFileLogWriter(logFilename, false )) gLogger.Info( "Current time is : %s" , time.Now().Format( "15:04:05 MST 2006/01/02" )) //exit(); gLogger.Close(); return } |
结果是:
问题依旧。
17.参考:
http://godoc.org/code.google.com/p/log4go#Exit
去试试:
1 2 | //gLogger.Close(); log4go.Exit(); |
结果是:
问题依旧。
18.后来,看到了:
中的解释:
(1)log4go的文档,很明显不是最新的,用的函数也是旧的函数:这点我早已发现,并且改正了;
(2)存在flush的bug,main函数退出太快的话,会导致无输出,或者输出内容部分丢失:我此处就是这样的问题。
(3)参考那人的解释,去手动加上flush的动作试试:
在main函数最后所调用的deinitAll函数中加上:
1 2 3 4 5 6 7 8 9 10 | //de-init for all func deinitAll(){ gCurCookies = nil if (nil == gLogger) { gLogger.Close(); os.Stdout.Sync() //try manually flush, hope can fix log4go's bug gLogger = nil } } |
看看效果:
结果还是无输出。。。
19.想起来了,此处是刚才把stdout禁止了。
现在去加上:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | //init for logger func initLogger(){ //var filenameOnly string //filenameOnly = GetCurFilename() //var logFilename string = filenameOnly + ".log"; var logFilename string = "log4go_debug_1.log" ; //gLogger = log4go.NewLogger() //gLogger = make(log4go.Logger) //for console //gLogger.AddFilter("stdout", log4go.INFO, log4go.NewConsoleLogWriter()) //gLogger.AddFilter("stdout", log4go.INFO, log4go.NewConsoleLogWriter()) gLogger = log4go.NewDefaultLogger(log4go.INFO) //for log file if _, err := os.Stat(logFilename); err == nil { //fmt.Printf("found old log file %s, now remove it\n", logFilename) os.Remove(logFilename) } //gLogger.AddFilter("logfile", log4go.FINEST, log4go.NewFileLogWriter(logFilename, true)) //gLogger.AddFilter("logfile", log4go.FINEST, log4go.NewFileLogWriter(logFilename, false)) gLogger.AddFilter( "log" , log4go.FINEST, log4go.NewFileLogWriter(logFilename, false )) gLogger.Info( "Current time is : %s" , time.Now().Format( "15:04:05 MST 2006/01/02" )) //exit(); //gLogger.Close(); //log4go.Exit(); return } |
结果是:
问题依旧,还是无输出。。。
20.去试试,在main函数最后,加上sleep的代码:
1 | time.Sleep( 1000 * time.Millisecond) |
结果是
真的可以了!!!
即:
不论是log文件,还是console,都可以正常输出log信息了。。。
21.再去注释掉sleep的话:
1 | //time.Sleep(1000 * time.Millisecond) |
看看结果:
果然真的没有输出。
22.再去对于sleep时间改短点,比如只有100毫秒:
1 2 | //time.Sleep(1000 * time.Millisecond) time.Sleep( 100 * time.Millisecond) |
结果是:
也正常,可以输出去全部log信息。
23.继续去缩短sleep的时间,看看10毫秒如何:
1 2 3 | //time.Sleep(1000 * time.Millisecond) //time.Sleep(100 * time.Millisecond) time.Sleep( 10 * time.Millisecond) |
结果也是可以的。
再次证明:
log4go,的确是有bug;
而手动加stdout的sync是没用的
但是加上sleep就有用,
而且是sleep一个很短的时间,比如10毫秒,就足够了,就可以保证所有的log信息正常输出了。
24.再去把之前正常的代码,都加上:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 | /* * [File] * EmulateLoginBaidu.go * * [Function] * 【记录】用go语言实现模拟登陆百度 * * [Version] * 2013-09-19 * * [Contact] */ package main import ( //"fmt" //"builtin" //"log" "os" "runtime" "path" "strings" "time" //"io" "io/ioutil" "net/http" //"net/http/cookiejar" //"sync" //"net/url" ) //import l4g "log4go.googlecode.com/hg" //import l4g "code.google.com/p/log4go" import "code.google.com/p/log4go" /*************************************************************************************************** Global Variables ***************************************************************************************************/ var gCurCookies []*http.Cookie; var gLogger log4go.Logger; /*************************************************************************************************** Functions ***************************************************************************************************/ //do init before all others func initAll(){ gCurCookies = nil gLogger = nil initLogger() initCrifanLib() } //de-init for all func deinitAll(){ gCurCookies = nil if (nil == gLogger) { gLogger.Close(); //os.Stdout.Sync() //try manually flush, but can not fix log4go's flush bug gLogger = nil } } //do some init for crifanLib func initCrifanLib(){ gLogger.Debug( "init for crifanLib" ) gCurCookies = nil return } //init for logger func initLogger(){ var filenameOnly string = GetCurFilename() var logFilename string = filenameOnly + ".log" ; //var logFilename string = "log4go_debug_1.log"; //gLogger = log4go.NewLogger() //gLogger = make(log4go.Logger) //for console //gLogger.AddFilter("stdout", log4go.INFO, log4go.NewConsoleLogWriter()) //gLogger.AddFilter("stdout", log4go.INFO, log4go.NewConsoleLogWriter()) gLogger = log4go.NewDefaultLogger(log4go.INFO) //for log file if _, err := os.Stat(logFilename); err == nil { //fmt.Printf("found old log file %s, now remove it\n", logFilename) os.Remove(logFilename) } //gLogger.AddFilter("logfile", log4go.FINEST, log4go.NewFileLogWriter(logFilename, true)) //gLogger.AddFilter("logfile", log4go.FINEST, log4go.NewFileLogWriter(logFilename, false)) gLogger.AddFilter( "log" , log4go.FINEST, log4go.NewFileLogWriter(logFilename, false )) gLogger.Info( "Current time is : %s" , time.Now().Format( "15:04:05 MST 2006/01/02" )) return } // GetCurFilename // Get current file name, without suffix func GetCurFilename() string { _, fulleFilename, _, _ := runtime.Caller( 0 ) //fmt.Println(fulleFilename) var filenameWithSuffix string filenameWithSuffix = path.Base(fulleFilename) //fmt.Println("filenameWithSuffix=", filenameWithSuffix) var fileSuffix string fileSuffix = path.Ext(filenameWithSuffix) //fmt.Println("fileSuffix=", fileSuffix) var filenameOnly string filenameOnly = strings.TrimSuffix(filenameWithSuffix, fileSuffix) //fmt.Println("filenameOnly=", filenameOnly) return filenameOnly } //get url response html func GetUrlRespHtml(url string) string{ gLogger.Info( "GetUrlRespHtml, url=%s" , url) var respHtml string = "" ; resp, err := http.Get(url) //gLogger.Info("http.Get done") if err != nil { gLogger.Warn( "http get url=%s response error=%s\n" , url, err.Error()) } gLogger.Debug( "resp.Header=%s" , resp.Header) gLogger.Debug( "resp.Status=%s" , resp.Status) defer resp.Body.Close() // gLogger.Info("defer resp.Body.Close done") body, errReadAll := ioutil.ReadAll(resp.Body) //body, _ := ioutil.ReadAll(resp.Body) //fmt.Println("ioutil.ReadAll done") //fmt.Println("resp.Body.Close done") //gLogger.Info("ioutil.ReadAll done") //fmt.Println("gLogger.Info done") if errReadAll != nil { gLogger.Warn( "get response for url=%s got error=%s\n" , url, errReadAll.Error()) } //gLogger.Debug("body=%s\n", body) gCurCookies = resp.Cookies() //gLogger.Info("resp.Cookies done") //fmt.Println("resp.Cookies done") //respHtml = "just for test log ok or not" respHtml = string(body) //gLogger.Info("resp body []byte to string done") return respHtml } func printCurCookies() { var cookieNum int = len(gCurCookies); gLogger.Info( "cookieNum=%d" , cookieNum) for i := 0 ; i < cookieNum; i++ { var curCk *http.Cookie = gCurCookies[i]; //gLogger.Info("curCk.Raw=%s", curCk.Raw) gLogger.Info( "------ Cookie [%d]------" , i) gLogger.Info( "Name\t=%s" , curCk.Name) gLogger.Info( "Value\t=%s" , curCk.Value) gLogger.Info( "Path\t=%s" , curCk.Path) gLogger.Info( "Domain\t=%s" , curCk.Domain) gLogger.Info( "Expires\t=%s" , curCk.Expires) gLogger.Info( "RawExpires=%s" , curCk.RawExpires) gLogger.Info( "MaxAge\t=%d" , curCk.MaxAge) gLogger.Info( "Secure\t=%t" , curCk.Secure) gLogger.Info( "HttpOnly=%t" , curCk.HttpOnly) gLogger.Info( "Raw\t=%s" , curCk.Raw) gLogger.Info( "Unparsed=%s" , curCk.Unparsed) } } func main() { initAll() gLogger.Info( "this is EmulateLoginBaidu.go" ) //step1: access baidu url to get cookie BAIDUID var baiduMainUrl string //baiduMainUrl := "http://www.baidu.com/"; //var baiduMainUrl string = "http://www.baidu.com/"; gLogger.Info( "baiduMainUrl=%s" , baiduMainUrl) respHtml := GetUrlRespHtml(baiduMainUrl) gLogger.Debug( "respHtml=%s" , respHtml) printCurCookies() //gLogger.Error("why log can not show ????????") //var cookieNameListToCheck []string = ["BAIDUID"] //toCheckCookieNameList := [1]string{"BAIDUID"} toCheckCookieNameList := []string{ "BAIDUID" } toCheckCookieNum := len(toCheckCookieNameList) gLogger.Info( "toCheckCookieNum=%d" , toCheckCookieNum) //toCheckCookieNum=1 //fmt.Printf("toCheckCookieNum=%d\n", toCheckCookieNum) //toCheckCookieNum=1 for i := 0 ; i < toCheckCookieNum; i++ { cookieName := toCheckCookieNameList[i]; gLogger.Info( "[%d]cookieName=%s" , i, cookieName) //fmt.Printf("[%d]cookieName=%s\n", i, cookieName) //[0]cookieName=BAIDUID } deinitAll() //【workaround】go语言中用log4go输出信息时有bug:只输出部分信息,甚至是无任何输出 time.Sleep( 10 * time.Millisecond) } |
看看结果是否也正常:
结果是:
偶尔,还是会输出内容不全的。
大部分的时候,已经正常了,够用了。
所以,看起来,至少此处的,sleep给的10ms,还是不太够。
所以,还是去改为更大点的时间,比如之前的100ms:
【总结】
至此,终于清楚根本原因了:
log4go,本身这个库还是不错的,
只不过,到目前为止:2013-09-20
还是有bug的,其中一个bug是:
其内部是通过channel去将log内容输出,到console和log文件中的;
而如果你的程序(main函数)退出的太快
就会导致log信息,来不及输出,你的程序就退出了。
从而导致:
你用log4go输出的信息,部分的,甚至全部的,都丢失了
从而在你的console和(或)你的log文件中,看不到log信息
解决办法:
在你的main函数,退出之前,加上对应的sleep,即可。
比如:
1 | time.Sleep( 100 * time.Millisecond) |
即可保证:
你的log信息,都可以正常输出。
感慨:
log4go,不错的模块,可是这样的bug却浪费了我大量的时间。。。哎,无语。。。
转载请注明:在路上 » 【workaround】go语言中用log4go输出信息时有bug:只输出部分信息,甚至是无任何输出