为什么在Golang中,日志实例不能在另一个包中共享?

huangapple go评论75阅读模式
英文:

Why package log instance can't share to another package in Golang

问题

我的项目有一些包,我不想在函数之间传递日志实例,而是在这些包中使用一个全局日志实例。

这是我做的演示,但是运行go run main.go后,日志/replica.log中没有打印任何内容。

我的代码有什么问题?

├── log
     └── replica.log
├── logs
     └── logs.go
├── main.go

main.go的内容如下:

package main

import (
	"./logs"
)

func main() {
	logs.Debug("hello")
}

logs.go的内容如下:

package logs

import (
	logging "github.com/op/go-logging"
	"os"
)

var log = logging.MustGetLogger("replica")
var format = logging.MustStringFormatter(
	`%{time:2006-01-02 15:04:05} [%{level:.4s}] %{shortfile}: %{message}`,
)

func init() {
	f, err := os.OpenFile("log/replica.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		panic(err)
	}
	defer f.Close()

	backend1 := logging.NewLogBackend(f, "", 0)
	backend1Formatter := logging.NewBackendFormatter(backend1, format)
	logging.SetBackend(backend1Formatter)
}

func Debug(args ...interface{}) {
	log.Debug(args)
}
英文:

My project has some packages, I don't want to pass log instance from one function to another, instead use a global log instance in there packages.

Here is the demo I have done, but run go run main.go, nothing print in logs/replica.log.

What's wrong with my code?

├── log
│   └── replica.log
├── logs
│   └── logs.go
├── main.go



$ cat main.go

<!-- language: lang-golang -->

package main

import (
	&quot;./logs&quot;
)

func main() {
	logs.Debug(&quot;hello&quot;)
}

$ cat logs/logs.go

<!-- language: lang-golang -->

package logs

import (
	logging &quot;github.com/op/go-logging&quot;
	&quot;os&quot;
)

var log = logging.MustGetLogger(&quot;replica&quot;)
var format = logging.MustStringFormatter(
	`%{time:2006-01-02 15:04:05} [%{level:.4s}] %{shortfile}: %{message}`,
)

func init() {
	f, err := os.OpenFile(&quot;log/replica.log&quot;, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		panic(err)
	}
	defer f.Close()

	backend1 := logging.NewLogBackend(f, &quot;&quot;, 0)
	backend1Formatter := logging.NewBackendFormatter(backend1, format)
	logging.SetBackend(backend1Formatter)
}

func Debug(args ...interface{}) {
	log.Debug(args)
}

答案1

得分: 1

是的,logs/logs.go:init()中的defer是问题所在。为什么会是问题呢?让我们来看一下Go语言规范,特别是关于延迟语句的部分:

> “defer”语句会调用一个函数,该函数的执行被延迟到包围它的函数体[...]达到函数体末尾的时刻。

当达到init函数体的末尾时,文件会被关闭。请记住,没有好的方法来优雅地关闭全局文件。

英文:

Yes, the defer in logs/logs.go:init() is the issue. Why is that the issue? Let's take a look at the Go Language Spec, specifically the section on Defer statements:

> A "defer" statement invokes a function whose execution is deferred to the moment the surrounding function [...] reache

展开收缩
the end of its function body [...].

The file is closed when the end of the init function body is reached. Keep in mind, there's no good way to gracefully close a global file.

huangapple
  • 本文由 发表于 2016年2月26日 10:20:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/35642220.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定