Можно ли увеличить fmt.print с уровнем отступа по умолчанию?

Я возился с созданием модулей и их связыванием.

При тестировании поведения я вызываю пакеты, которые вызывают другие пакеты.

Есть ли простой способ изменить поведение пакета fmt с уровнем отступа будущих вызовов. Чтобы родитель мог установить уровень отступа +1 перед вызовом дочернего пакета.

Таким образом, когда каждая функция выводит вывод, я могу легко увидеть каскадные зависимости в стандартном выводе:

inside main
calling package X
____entering package X
____calling package Y
________package Y hello world
____leaving package X
back in main.
exiting 

person GoTTimw    schedule 15.09.2020    source источник
comment
Это не является частью функциональности пакета fmt.   -  person Adrian    schedule 15.09.2020
comment
Можно ли расширять... Нет. Go не позволяет расширять вещи. Лучшее, что вы можете сделать, это завернуть вещи.   -  person Flimzy    schedule 15.09.2020


Ответы (2)


Пакет fmt не поддерживает это по умолчанию.

Однако вы можете получить доступ к глубине вызова с помощью runtime.Callers(), что означает, что вы не даже не нужно поддерживать уровень отступа вручную.

Доказательство концепции

Доступ к глубине вызова выглядит следующим образом (который возвращает 0 для main(), 1 для функции, вызываемой из main() и т. д.):

func callDepth() int {
    pc := make([]uintptr, 100)
    return runtime.Callers(6, pc)
}

И используя его, функцию автоматической печати индентора:

var tabs = strings.Repeat("\t", 100)

func Println(args ...interface{}) {
    fmt.Print(tabs[:callDepth()])
    fmt.Println(args...)

}

Давайте посмотрим на это в действии:

func main() {
    Println("In main()")
    f1()
    Println("In main() again")
}

func f1() {
    Println("In f1()")
    f2()
    Println("In f1() again")
}

func f2() {
    Println("In f2()")
}

Какие результаты (попробуйте на Go Playground):

In main()
    In f1()
        In f2()
    In f1() again
In main() again

Заметки

Я назвал вышеприведенное решение доказательством концепции, поскольку оно не подходит для всех случаев. Вы должны решить, как вы хотите обрабатывать запуск новых горутин. Когда запускаются новые горутины, они не вызываются из main(), поэтому пропускаемые кадры, передаваемые в runtime.Callers(), должны быть меньше 1 (runtime.Callers(5, pc) вместо runtime.Callers(6, pc)). Чтобы узнать, как это обнаружить, см. если функция вызывается как горутина или нет.

person icza    schedule 15.09.2020

Напишите небольшую оболочку вокруг функций fmt, которые вы хотите вести так, чтобы они принимали дополнительный параметр уровня отступа.

package main

import "fmt"

// Println  replacement
func Println(level int, args ...interface{}) {
    for i := level; i > 0; i-- {
        fmt.Print("__")
    }
    fmt.Println(args...)
}

func main() {
    Println(0, "here")
    Println(1, "there")
    Println(2, "everywhere")
    Println(2, "Yes, everywhere")
}
person Vorsprung    schedule 15.09.2020