为了简化对我负责测试的代码的测试,我将重构团队的LogHandler
。
他们有这样的东西:
type LogHandlerSt struct {
path string
fileName string
projectName string
}
var (
//Instance The project instance of log handler.
Instance LogHandlerSt
//OnResponseError A function that can be set to be called on response error.
OnResponseError func(context interface{}, response *http.Response)
//includeStack Will include all lines with the strings below in the debug stack.
includeStack = []string{"apiserver_sdk", "ezdineserver_sdk"}
)
//CreateLogHandler Creates and assigns a log handler instance for use by the project.
func CreateLogHandler(path string, fileName string, projectName string) LogHandlerSt {
Instance = LogHandlerSt{path: path, fileName: fileName, projectName: projectName}.
fmt.Println("Log files are in \"" + path + "\"")
return Instance
}
//log Logs a message given the type of message and the message itself.
func (handler *LogHandlerSt) log(logType string, errMsg string) {
fmt.Println(errMsg)
logFile, err := os.OpenFile(handler.path+"/"+handler.fileName+" "+time.Now().Format("2006-01-02")+".log", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0777)
if err != nil {
fmt.Println(err)
}
defer logFile.Close()
if _, err = logFile.WriteString(`
` + logType + " " + time.Now().Format("2006-01-02 15:04:05.000") + `: ` + errMsg + "\n"); err != nil {
fmt.Println(err)
}
logFile.Sync()
}
//GetProjectNames Gets the projects to use for the log handler instance. Usually used for the debug stack.
func (handler *LogHandlerSt) GetProjectNames() []string {
var projectNames = []string{handler.projectName}
projectNames = append(projectNames, includeStack...)
return projectNames
}
//LogError Logs an error given information.
func (handler *LogHandlerSt) LogError(errMsg string) {
handler.log("Error", errMsg)
}
//LogWarning Logs a warning given information.
func (handler *LogHandlerSt) LogWarning(errMsg string) {
handler.log("Warn", errMsg)
}
//LogInfo Logs some information.
func (handler *LogHandlerSt) LogInfo(errMsg string) {
handler.log("Info", errMsg)
}
受测试的代码库中的许多方法都在Instance
上使用这些功能。为了解决这个问题,我由此引入了一个结构Logger
:
// Logger provides a generic implementation of the required methods.
// Provided for testing purposes
type Logger interface {
LogError(errMessage string)
LogWarning(errMessage string)
LogInfo(errMessage string)
}
本能,尤其是Java的本能告诉我将Instance
的声明更改为Logger
。当然,这没有做任何事情,因为Logger
是一个实例,而方法在*Logger
上。因此,我更改为Instance *Logger
并重构了CreateLogHandler
来处理刚创建的编译时错误:
//CreateLogHandler Creates and assigns a log handler instance for use by the project.
func CreateLogHandler(path string, fileName string, projectName string) LogHandlerSt {
Instance = &LogHandlerSt{path: path, fileName: fileName, projectName: projectName}
fmt.Println("Log files are in \"" + path + "\"")
return Instance
}
我被告知:
cannot use LogHandlerSt literal (type *LogHandlerSt) as type *Logger in assignment:
*Logger is pointer to interface, not interface
为什么不,我该怎么办?
答案 0 :(得分:1)
“作为
Logger
是一个实例,而方法在*Logger
”上。
在那停。 Logger
是一个界面。方法是“不在接口上”。具体的实现具有具体的接收者类型,它将是*LogHandlerSt
,而不是*Logger
也不是Logger
。同样,LogHandlerSt
没有实现Logger
,只有*LogHandlerSt
是用指针接收器定义的方法。
如果您介绍Logger
,则可以使用它:
var Instance Logger
func CreateLogHandler(path string, fileName string, projectName string) Logger {
Instance = &LogHandlerSt{
path: path,
fileName: fileName,
projectName: projectName
}
fmt.Println("Log files are in \"" + path + "\"")
return Instance
}
由于只有*LogHandlerSt
实现了Logger
,所以您必须分配一个指向Instance
的指针。
请注意,您很少(如果有的话)使用指向接口的指针(例如*Logger
)。相反,应将指向具体类型的指针包装在接口值中。