尝试在Golang中将文字转化为指针

时间:2018-08-17 15:16:00

标签: go methods struct interface

为了简化对我负责测试的代码的测试,我将重构团队的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

为什么不,我该怎么办?

1 个答案:

答案 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)。相反,应将指向具体类型的指针包装在接口值中。