golang的init()如何工作。我很困惑

时间:2018-11-09 11:15:34

标签: go

我在“ config / config.go”中定义了一个init()函数

config.go

<div class="col-lg-9 col-md-6">
....
</div>

div class="col-lg-3 col-md-6">
...
</div>

我在身份验证包中还有一个名为auth.go的go文件

package config

import(
    log "github.com/sirupsen/logrus"
)

func init() {
    log.SetReportCaller(true)
}

在auth.go中调用log.Info()时,日志显示如下

package auth

import(
    log "github.com/sirupsen/logrus"
)

func auth(username string, pwd string) {
     //some auth code
    log.Info("Auth success")
}

我在这里感到困惑的是,auth.go中的“ log”如何知道在2018-11-09T16:38:27+05:30 auth/auth.go:36 level=info msg="Auth success" 中完成的设置。 config.go位于log.SetReportCaller()中,但是即使记录了config.go,它也需要进行log.SetReportCaller()的设置,该设置是在config.go中完成的。

由于未在auth.go中设置log.SetReportCaller(),因此预期日志应如下所示,而不显示调用方方法的行号。

auth.go

main.go

2018-11-09T16:38:27+05:30 level=info msg="Auth success"

auth / router.go

package main

import (
    "path/to/auth" 
    log "github.com/sirupsen/logrus"
    "net/http"
 )

func main() {
    r := server.Route()

    log.Info("Listening on 8080")

    http.Handle("/", r)
    log.Fatal(http.ListenAndServe(":8080", nil))
}

auth / login.go

package auth

import (
    "github.com/gorilla/mux"
    "github.com/rs/cors"
    "net/http"
)

func Route() http.Handler {
    r := mux.NewRouter()
    // UI handlers
    r.HandleFunc("/", IndexPageHandler)
    r.HandleFunc("/login", LoginHandler).Methods("POST")
    handler := cors.Default().Handler(r)
    return 
}

请解释这是怎么发生的

2 个答案:

答案 0 :(得分:4)

检查此图以了解init()的工作方式:diagram

初始化顺序如下

  1. 如果一个软件包导入了其他软件包,则首先初始化导入的软件包。

  2. 然后初始化包装级别变量。

  3. 接下来调用当前程序包的
  4. init函数。程序包可以具有多个init函数(在单个文件中或分布在多个文件中),并且按照将其呈现给编译器的顺序进行调用。

您将找到一个解释此here的示例。

我怀疑在依赖关系树中,有一个共同的祖先文件同时导入config包和auth包。

以下是初始化的官方文档:Package initialization

UPD::添加了各自的代码后,我们可以直观地看到这里发生的情况。看下面的图片,

enter image description here

发生了什么事

  1. 您的程序包开始初始化。但是它已经导入了 auth 软件包。因此,要完成初始化,必须初始化 auth 程序包。
  2. auth 软件包开始初始化。但是它已经导入了 config 软件包。因此,要完成初始化,必须初始化 config 软件包。
  3. config 程序包完成初始化(称为log.SetReportCaller(true))。
  4. auth 程序包完成初始化。
  5. 主要程序包已完成初始化。
  6. main()函数开始执行...

答案 1 :(得分:1)

您要询问的行为实际上与init()函数的工作方式无关。 SetReportCallergithub.com/sirupsen/logrus中而不是在configauth包中设置全局变量。因此,在何处调用该函数或在何处调用log.Info等都无关紧要;该设置会影响所有对数呼叫的呼叫,无论呼叫来源如何。