如何在golang中使用并发日志?

deF*_*tas 7 concurrency logging go

我已经搜索过它,只在这里这里找到,但它并没有解决我的问题.

我如何使用标准方法识别分隔并发日志的日志,如JAVA与线程ID?因为如果我有一个并发方法,他们的日志将在输出中打印混合,所以我认为LOGGER需要有一种方法来识别每个请求"线程"

例如:

package main

import "log"

func main() {

    /* simulating 10000 users requests  */
    i := 1;
    for ;i < 10000; i++ {
        go getHello(i)
    }

}

func getHello(d int){
    log.Printf("m=getHello, i=%d,begin", d)
    log.Println("m=getHello, processing the hello message")
    log.Printf("m=getHello, i=%d, end", d)
}
Run Code Online (Sandbox Code Playgroud)

产量

2016/07/29 15:59:46 m=getHello, i=1017,begin
2016/07/29 15:59:46 m=getHello, processing the hello message
2016/07/29 15:59:46 m=getHello, i=1017, end
2016/07/29 15:59:46 m=getHello, processing the hello message
2016/07/29 15:59:46 m=getHello, i=1038, end
2016/07/29 15:59:46 m=getHello, i=311,begin
2016/07/29 15:59:46 m=getHello, processing the hello message
2016/07/29 15:59:46 m=getHello, i=311, end
2016/07/29 15:59:46 m=getHello, i=1023,begin
2016/07/29 15:59:46 m=getHello, processing the hello message
2016/07/29 15:59:46 m=getHello, i=1023, end
2016/07/29 15:59:46 m=getHello, i=991,begin
2016/07/29 15:59:46 m=getHello, processing the hello message
2016/07/29 15:59:46 m=getHello, i=991, end
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,如果我没有int标志,则无法知道请求记录的内容.在java,c,c#,delphy例如我简单记录了线程id,一切正常.

你能帮我在Golang做些什么吗?谢谢.

Obs:如果我的问题不好请告诉我为什么评论

Pau*_*kin 8

运行时没有可用的goroutine ID.Goroutines比其他语言中的线程使用得更加宽松,因此goroutine处理特定请求或项目的想法在较大的程序中可能不太明确.

所以你需要自己通过一个ID进行日志记录.你可以直接通过int自己,但context模块很方便:除了允许用户定义的值,它可以处理项目取消和截止日期,这些也可能对你有用.

这是一个如何使用它的粗略示例.我添加了一个简单的日志记录对象,可以用作上下文感知记录器.它记录创建上下文的ID.可能这个记录器会在一个真正的程序中包含它自己的包,并支持更多日志包的功能,而不仅仅是PrintfPrintln.

package main

import (
    "fmt"
    "log"
    "sync"
    "context"
)

type logger int
const loggerID = "logger_id"

func (l logger) Printf(s string, args ...interface{}) {
    log.Printf("[id=%d] %s", l, fmt.Sprintf(s, args...))
}

func (l logger) Println(s string) {
    log.Printf("[id=%d] %s\n", l, s)
}

func ctxWithLoggerID(ctx context.Context, id int) context.Context {
    return context.WithValue(ctx, loggerID, id)
}

func getLogger(ctx context.Context) logger {
    return logger(ctx.Value(loggerID).(int))
}

func main() {
    ctx := context.Background()
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go hello(ctxWithLoggerID(ctx, i), &wg)
    }
    wg.Wait()
}

func hello(ctx context.Context, wg *sync.WaitGroup) {
    defer wg.Done()
    log := getLogger(ctx)
    log.Printf("hello begin")
    log.Println("hello, processing the hello message")
    log.Printf("hello, end")
}
Run Code Online (Sandbox Code Playgroud)

这是你的问题的附带条件,但我sync.WaitGroup在你的程序中添加了一个,以便main等到所有工人都完成后再退出.这允许使用较少数量的工作程序(10而不是原始10000)来测试代码.