Как работает init Голанга ().я сбит с толку - PullRequest
0 голосов
/ 09 ноября 2018

У меня есть функция init (), определенная в "config / config.go"

config.go

package config

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

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

У меня есть другой файл go с именем auth.go в пакете auth

package auth

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

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

Когда log.Info () вызывается в auth.go, журнал печатается, как показано ниже

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

Что меня смущает, так это то, как «log» в auth.go знает о настройках, выполненных в config.go. log.SetReportCaller() находится в config.go, но даже когда auth.go зарегистрирован, он принимает настройки log.SetReportCaller () выполняется в config.go

Поскольку log.SetReportCaller () не установлен в auth.go, ожидаемый журнал должен быть таким, как показано ниже, без указания номера строки метода вызывающего абонента.

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))
}

авториз / 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 
}

авториз / 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

}

Пожалуйста, объясните, как это происходит

Ответы [ 2 ]

0 голосов
/ 09 ноября 2018

Поведение, о котором вы спрашиваете, на самом деле не имеет ничего общего с тем, как работают init() функции. SetReportCaller устанавливает глобальную переменную в github.com/sirupsen/logrus, а не в ваши пакеты config или auth. Поэтому не имеет значения, где вы вызываете эту функцию или где вы вызываете log.Info и др .; настройка влияет на все вызовы в logrus независимо от источника вызова.

0 голосов
/ 09 ноября 2018

Проверьте эту диаграмму, чтобы понять, как init() работает: диаграмма

Порядок инициализации следующий,

  1. Если пакет импортирует другие пакеты, импортированные пакеты инициализируются первыми.

  2. Затем инициализируются переменные уровня пакета.

  3. вызывается функция init текущего пакета. Пакет может иметь несколько функций инициализации (либо в одном файле, либо в нескольких файлах), и они вызываются в том порядке, в котором они представлены компилятору.

Вы найдете пример, объясняющий это здесь .

Я подозреваю, что в дереве зависимостей есть общий файл предков, который импортирует как пакет config, так и пакет auth.

Вот официальный документ об инициализации: Инициализация пакета

UPD: Поскольку вы добавили соответствующие коды, давайте представим, что здесь происходит. Посмотрите на картинку ниже,

enter image description here

Что происходит:

  1. Ваш основной пакет инициализируется. Но он импортировал auth пакет. Таким образом, для завершения инициализации пакет auth должен быть инициализирован.
  2. auth Начать инициализацию пакета. Но он импортировал пакет config . Таким образом, для завершения инициализации пакет config должен быть инициализирован.
  3. config полная инициализация пакета (вызывается log.SetReportCaller(true)).
  4. auth полная инициализация пакета.
  5. main полная инициализация пакета.
  6. main() функция начинает выполняться ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...