Официальная позиция языка такая:
Goroutines do not have names; they are just anonymous workers. They expose no unique identifier, name, or data structure to the programmer. Some people are surprised by this, expecting the go statement to return some item that can be used to access and control the goroutine later.
The fundamental reason goroutines are anonymous is so that the full Go language is available when programming concurrent code. By contrast, the usage patterns that develop when threads and goroutines are named can restrict what a library using them can do.
Однако, иногда бывает нужно получить номер горутины, например, чтобы написать рекурсивный мьютекс, которого в Go нет, в отличие, например, от Java. Совсем недавно писали такой мьютекс на курсе.
Чтобы получить ID горутины, можно использовать stack trace
(Go Playground):
func Get() int64 {
var buf [64]byte
runtime.Stack(buf[:], false)
s := buf[len("goroutine "):]
s = s[:bytes.IndexByte(s, ' ')]
gid, _ := strconv.ParseInt(string(s), 10, 64)
return gid
}
Однако реализация через стектрейс довольно дорогая. Поэтому, более эффективно достать контекст горутины с помощью ассемблера, получив доступ к id:
// func getg() *g
TEXT ·getg(SB),NOSPLIT,$0-8
#ifdef GOARCH_386
MOVL (TLS), AX
MOVL AX, ret+0(FP)
#endif
#ifdef GOARCH_amd64
MOVQ (TLS), AX
MOVQ AX, ret+0(FP)
#endif
#ifdef GOARCH_arm
MOVW g, ret+0(FP)
#endif
#ifdef GOARCH_arm64
MOVD g, ret+0(FP)
#endif
#ifdef GOARCH_s390x
MOVD g, ret+0(FP)
#endif
RET
func Get() int64 {
return getg().goid
}
Более того, на гитхабе есть библиотека, которая поддерживает доступ к goroutineID для версий Go 1.3 и выше.
Важно понимать, что подобные решения не гарантируют обратную совместимость и их нужно использовать аккуратно.
Пишите в комментариях, какие темы осветить в будущих постах!