I am messing around creating modules and interlinking them.
When testing out behaviours I am calling packages that call other packages.
Is there an easy way to modify behaviour of fmt package with indentation level of future calls. So that parent can sets indentation level +1 before calling child package.
This way when each function prints out output I can easily see cascading dependencies in the stdout:
inside main
calling package X
____entering package X
____calling package Y
________package Y hello world
____leaving package X
back in main.
exiting
The fmt
package does not support this out of the box.
However, you can access the call depth with the help of runtime.Callers()
, which means you don't even have to maintain the indentation "level" manually.
Accessing the call depth is like this (which returns 0
for main()
, 1
for a function called from main()
etc.):
func callDepth() int {
pc := make([]uintptr, 100)
return runtime.Callers(6, pc)
}
And using it, an auto-indenter printing function:
var tabs = strings.Repeat("\t", 100)
func Println(args ...interface{}) {
fmt.Print(tabs[:callDepth()])
fmt.Println(args...)
}
Let's see it in action:
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()")
}
Which outputs (try it on the Go Playground):
In main()
In f1()
In f2()
In f1() again
In main() again
I called the above solution "proof of concept" because it's not a solution handling all cases. You have to decide how you want to handle when new goroutines are launched. When new goroutines are launched, they are not called from main()
, so the skip frames passed to runtime.Callers()
should be 1-less (runtime.Callers(5, pc)
instead of runtime.Callers(6, pc)
). For how to detect this, see Check if function is being called as goroutine or not.