golang的log包求助

@Ta 2023-06-15发布,2023-06-15修改 9955点击

一个奇怪的go的log包的Bug


	startInfo := bytes.Buffer{}
	startInfo.WriteByte('[')
	startInfo.WriteString(register.Name)
	startInfo.WriteString("] Starting  server at -> ")
	startInfo.WriteString(register.ListenAddr)
	startInfo.WriteString(" ;Listening...")
	fmt.Println("ok1")
	log.Println(startInfo.Bytes())
	fmt.Println("ok2")

运行结果:


2023/06/15 17:16:58 ok1

2023/06/15 17:16:58 [91 66 117 115 105 110 101 115 115 229 164 132 231 144 134 229 153 168 93 32 83 116 97 114 116 105 110 103 32 32 115 101 114 118 101 114 32 97 116 32 45 62 32 58 49 50 51 56 32 59 76 105 115 116 101 110 105 110 103 46 46 46]

2023/06/15 17:16:58 ok2

但是如果改为string()


	startInfo := bytes.Buffer{}
	startInfo.WriteByte('[')
	startInfo.WriteString(register.Name)
	startInfo.WriteString("] Starting  server at -> ")
	startInfo.WriteString(register.ListenAddr)
	startInfo.WriteString(" ;Listening...")
	fmt.Println("ok1")
	log.Println(startInfo.String())
	fmt.Println("ok2")

运行结果:


2023/06/15 17:16:58 ok1

结果卡住了一样,但是我设置了 log.setOutxx(file),file中是有没问题的都能记录下来,不存在阻塞

吧log换成fmt 也不会阻塞

回复列表(6|隐藏机器人聊天)
  • @Ta / 2023-06-15 / /

    我问了一下gpt4,以下是gpt4的回复,从你的描述看,这个问题可能并不是一个 bug,而是因为 log.Println()fmt.Println() 对待参数的方式有所不同。

    log.Println() 函数会为每个参数调用 fmt.Sprint() 来生成输出的字符串。在你的第一个例子中,你传递给 log.Println() 的是一个字节切片(startInfo.Bytes()),fmt.Sprint() 会将这个字节切片转换为一个字符串,其中每个字节都被转换为其对应的十进制数值,这就是为什么你看到一串数字的原因。

    在你的第二个例子中,你传递给 log.Println() 的是一个字符串(startInfo.String())。这个字符串应该能正常打印出来,但是你说结果卡住了。这可能是因为你的环境或者终端有些问题,或者是因为 register.ListenAddr 中包含了一些非打印字符,导致在终端上看起来像是卡住了。

    你提到你已经设置了 log.SetOutput(file),并且在文件中的记录是正常的,这说明 log.Println() 是正常工作的。你可以尝试在不同的终端或者环境下运行你的程序,看看是否还会出现同样的问题。

    如果使用 fmt.Println() 没有问题,那么在这种情况下,你可以继续使用 fmt.Println() 来打印日志。如果你需要的是将日志写入文件,那么你可能需要使用 log 包,因为 fmt 包并没有提供设置输出的功能。

    另外,你也可以尝试一下 log.Printf() 函数,这个函数允许你指定一个格式字符串,可以更精确地控制输出的格式。例如:

    log.Printf("[%s] Starting  server at -> %s ;Listening...\n", register.Name, register.ListenAddr)
    

    这样,你就不需要使用 bytes.Buffer 来手动构建字符串了。

  • @Ta / 2023-06-15 / /

    目前发现,只要有- 或者> 就会这样,去掉就正常,
    用strconv.Quote()解决,因为特殊符号被转义为实体动作了,或者用log.printf(“%s”,str)解决

  • @Ta / 2023-06-15 / /

    go version go1.20.4 darwin/arm64

    package main
    
    import (
    	"bytes"
    	"fmt"
    	"log"
    )
    
    type reg struct {
    	Name       string
    	ListenAddr string
    }
    
    func main() {
    	register := reg{
    		Name:       "123",
    		ListenAddr: "127.0.0.1",
    	}
    
    	flag := false
    	if flag {
    		startInfo := bytes.Buffer{}
    		startInfo.WriteByte('[')
    		startInfo.WriteString(register.Name)
    		startInfo.WriteString("] Starting  server at -> ")
    		startInfo.WriteString(register.ListenAddr)
    		startInfo.WriteString(" ;Listening...")
    		fmt.Println("ok1")
    		log.Println(startInfo.Bytes())
    		fmt.Println("ok2")
    	} else {
    		startInfo := bytes.Buffer{}
    		startInfo.WriteByte('[')
    		startInfo.WriteString(register.Name)
    		startInfo.WriteString("] Starting  server at -> ")
    		startInfo.WriteString(register.ListenAddr)
    		startInfo.WriteString(" ;Listening...")
    		fmt.Println("ok1")
    		log.Println(startInfo.String())
    		fmt.Println("ok2")
    	}
    
    }
    
    

    @胡椒舰长 复现不了,没发现阻塞

    ~~~

  • @Ta / 2023-06-15 / /

    @㝶芾厶眵攴䭡

    会不会和后面的阻塞函数有关,这是后面部分的

    server := &http.Server{
    		Addr:    register.ListenAddr,
    		Handler: handleServer,
    	}
    
    	var startError error
    	if register.TLS {
    		startError = server.ListenAndServeTLS("server.crt", "server.key")
    	} else {
    		startError = server.ListenAndServe()
    	}
    
    	if startError != nil {
    		return startError
    	}
    	//正常exit
    	return nil
    
  • @Ta / 2023-06-16 / /

    @胡椒舰长 ListenAndServe,看起来监听端口,要同步阻塞的,把他丢到goroutine里面吧
    ~~~

  • @Ta / 2023-06-16 / /

    @㝶芾厶眵攴䭡,这个和阻塞没关系,我还希望他阻塞,我只想找出log.Printf的阻塞问题,目前基本确定就是特殊符号了转义指令了

添加新回复
回复需要登录