Golang 导入包中的方法

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

Golang import methods from package

问题

现在我决定在我的Go程序中使用分级记录器。目前使用的是logrus。
但是经过一些调查(费了一些力气),我发现有很多记录器:glog、log15、logrus等等。所以,现在我想尝试使用logrus,并且希望能够在不修改所有使用日志的源代码的情况下将其更换为其他记录器。

我尝试创建了一个只导入logrus的自定义包logger:

package logger
import "github.com/Sirupsen/logrus"

func init() {
    logrus.SetFormatter(new(logrus.TextFormatter))    
}

在我的其他所有源代码中,我想以这种方式使用它:
// main.go

package main
import log "logger"

func main() {
   log.Print(...)
   log.Debug(...)
   // 其他方法
}

但是编译器告诉我logger包中没有这些方法。
有没有办法导入某个包A到我的自定义包B中,并通过B在我的代码中使用A的所有方法?

我需要这样做的原因是为了将来有机会快速将logrus更换为另一个支持相同方法的记录器,只需在我的自定义logger文件中替换几行代码,而不是在所有源代码中替换
import log "github.com/Sirupsen/logrus"import log "github.com/some_bestlogger"

英文:

Now i decided to use leveled logger in my Go programm. At this moment it's logrus.
But after some investigation (through pain) found that there are much loggers: glog, log15, logrus and so on. So, now i want try to use logrus and have
possibility to change it on another without fixing all my sources where log is used.

I tried to create my own package logger which only imports logrus:

package logger
import "github.com/Sirupsen/logrus"

func init() {
    logrus.SetFormater(new(logrus.TextFormater))    
}

In all other my sources a want to use i in such way:
// main.go

package main
import log "logger"

func main() {
   log.Print(...)
   log.Debug(...)
   and so on
}

But compiler says me that there are no such methods in logger package.
Is there a way just import some package A to my own package B and use in my code all methods of A through B?

The reason what i need this is to have a chance quickly change logrus to ahother logger in future which support same methods just replacing several lines of code in my own logger file without replacing
import log "github.com/Sirupsen/logrus" on import log "github.com/some_bestlogger" over all sources

答案1

得分: 2

你可以简单地导入你的logger包以获取其副作用,并直接使用logrus包:

package main

import (
	log "github.com/Sirupsen/logrus"
	_ "logger"
)

func main() {
	log.Print()
	log.Debug()
}

如果你确实想通过你的"logger"包直接调用这些日志函数,你需要定义这些函数并在内部委托给"logrus"包。

英文:

You can import your logger package simply for its side effects, and still use the logrus package directly:

package main

import (
	log "github.com/Sirupsen/logrus"
	_ "logger"
)

func main() {
	log.Print()
	log.Debug()
}

If you do want to be able to call those log function directly through your "logger" package, you will need to define the functions and delegate them to the "logrus" package internally.

答案2

得分: 1

你永远不会切换到其他日志记录器,因为每个日志记录器都有不同的方法集。例如,log15没有Print方法,而是Info方法。而且,不同的日志记录器对于日志字段(键值对)有完全不同的处理方式。你担心只需要改变一个导入行,但实际上你需要改变每一行使用日志记录器的代码。

如果你想要能够轻松地在不同的日志记录包之间切换,你需要设计自己的日志记录接口(或使用最适合你的接口),并在幕后使用你选择的日志记录包。只有这种方法才能最大程度地减少代码中的更改。

你还可以在你的库中提供一个接口,然后提供一个默认的日志记录器,该记录器将使用特定的实现。请注意,我所知道的所有日志记录器包都提供了某种类型的Logger结构(例如logrus.Logger),你可以将其附加到你的接口上。然后,你可以在整个应用程序中使用log = logger.New(),而不是更改导入的包名。

如果你不接受这些论点,而想要按照你的方式进行,从我的角度来看,你只需要一个_别名_。你可以fork其中一个日志记录库,并在整个代码中使用自己的fork(这样可以完全改变行为而不影响导入者),或者将你想要的导入路径建立符号链接,比如指向logrus(尽管这种方法在使用go get时可能不起作用)。

英文:

> to have a chance quickly change logrus to ahother logger in future which support same methods

You will never switch to anything else, as every logger has distinct method set. For example log15 doesn't have Print method, but Info. And completely different approach to logging fields (key-value pairs). You're worried about changing a single import line, but in fact you will need to change every single line which uses logger.

If you want to be able to easily switch between logging packages, you need to come up with own logging interface (or use one that fits you best) and use logging package of your choice behind the scenes. Only this approach gives you ability to minimise changes all around your code.

You could also provide an interface in your library and then provide a default logger which would use a particular implementation. Note that all logger packages I know provide some kind of Logger structure (e.g. logrus.Logger) which you could than attach to your interface. Then, instead of changing package name on import, you could use log = logger.New() across your application.

If you don't take these arguments and want to follow your path, from my perspective all you need is an alias. You can either fork one of the logging libraries and use own fork across your code (this would allow you to completely change the behaviour without affecting importers) or simply symlink your desired import path to, say, logrus (although this will not work with go get).

答案3

得分: 0

我认为你需要的是一个接口。这里有一个非常简单的例子。

package main

import (
	"os"

	"github.com/Sirupsen/logrus"
)

func init() {
	// 输出到标准输出而不是默认的标准错误
	// 可以是任何io.Writer,下面是一个文件示例
	logrus.SetOutput(os.Stdout)
}

type logInterface interface {
	Print()
}

type MyLogger struct{}

func (ml MyLogger) Print() {
	logrus.WithFields(logrus.Fields{
		"animal": "walrus",
		"size":   10,
	}).Info("一群海象从海洋中出现")
}

func main() {
	mylogger := MyLogger{}

	mylogger.Print()
}

通过这种方式,你可以用任何其他的日志包替换logrus,并且只需要更新Print函数,而不必更改调用Print函数的代码。

英文:

I think what you need is an interface. Here is a very simple example.

package main

import (
	"os"

	"github.com/Sirupsen/logrus"
)

func init() {
	// Output to stdout instead of the default stderr
	// Can be any io.Writer, see below for File example
	logrus.SetOutput(os.Stdout)
}

type logInterface interface {
	Print()
}

type MyLogger struct{}

func (ml MyLogger) Print() {
	logrus.WithFields(logrus.Fields{
		"animal": "walrus",
		"size":   10,
	}).Info("A group of walrus emerges from the ocean")
}

func main() {
	mylogger := MyLogger{}

	mylogger.Print()
}

In this way, you can replace logrus with any other logging package, and you just need to update the Print function and don't have to change the code where the Print function is called.

huangapple
  • 本文由 发表于 2015年12月10日 22:21:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/34204262.html
匿名

发表评论

匿名网友

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

确定