doutuoji8418 2018-11-09 11:15
浏览 55
已采纳

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

I have a init() function defined in "config/config.go"

config.go

package config

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

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

I have another go file called auth.go in auth package

package auth

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

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

When log.Info() is called in auth.go the log prints as below

2018-11-09T16:38:27+05:30 auth/auth.go:36 level=info msg="Auth success"

What I am confused here is that, how "log" in auth.go is aware of the settings done in config.go. log.SetReportCaller() is in config.go but even when auth.go is logged it takes settings of log.SetReportCaller() done in config.go

Since log.SetReportCaller() is not set in auth.go expected log should be as below without showing line number of caller method.

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

main.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/router.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 
}

auth/login.go

package auth

import (
    "fmt"
    "path/to/config"
    log "github.com/sirupsen/logrus"
    "net/http"
)
func LoginHandler(w http.ResponseWriter, r *http.Request) {

    username := r.FormValue("username")
    password := r.FormValue("password")

    status, userName, mail, _ := auth(username, password)
    //some code goes here

}

Kindly explain how this is happening

  • 写回答

2条回答 默认 最新

  • dongxuandong2045 2018-11-09 11:45
    关注

    Check this diagram to understand how init() work: diagram

    Initialization order are as follows,

    1. If a package imports other packages, the imported packages are initialised first.

    2. Package level variables are initialised then.

    3. init function of current package is called next. A package can have multiple init functions (either in a single file or distributed across multiple files) and they are called in the order in which they are presented to the compiler.

    You will found an example explaining this here.

    I am suspecting in dependency tree, there is a common ancestor file that import both config package and auth package.

    Here is official doc on initialization: Package initialization

    UPD: As you have added respective codes, let's visualize what is happening here. Look at the picture bellow,

    enter image description here

    What happening:

    1. Your main package start initialing. But it is has imported auth package. So to complete initialization, auth package must be initialized.
    2. auth package start initializing. But it has imported config package. So to complete initialization, config package must be initialized.
    3. config package complete initialization(log.SetReportCaller(true) is called).
    4. auth package complete initialization.
    5. main package complete initialization.
    6. main() function starts executing...
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?