I understand that there is no support for recursive mutexes in Go (and that a lot of folks consider these dangerous), and that channels are the preferred way to implement complex concurrency patterns.
However, I cannot figure out any sensible way to implement a very common concurrency pattern - that of the re-entrant or recursive critical section.
Roughly: goroutines A and B will compete for a lock over a critical section (say some state in a struct needs to be atomically modified). Let's say A receives the lock. However, A will recurse, possibly needing to enter the critical section many times. When it has exited the critical section as it has entered it, goroutine B will get the lock, etc.
I want to implement this with channels (or in any way possible in Go otherwise), without having to pass some string or token back and forth through the whole call tree of functions that might pass through the critical section (there is no "goroutine id" available)., and without having messy/expensive stack introspection necessary using runtime
package.
How can this be done?