Как я могу получить идентификатор времени выполнения горутины?

Как я могу получить идентификатор времени выполнения горутины?

Я получаю чередующиеся журналы из импортированного пакета — один из подходов — добавить уникальный идентификатор в журналы каждой горутины.

Я нашел несколько ссылок на runtime.GoID:

func worker() {
    id := runtime.GoID()
    log.Println("Goroutine ID:", id)
}

Но похоже, что это устарело/было удалено - https://pkg.go.dev/runtime?

Никогда не существовало идентификаторов области действия горутины. Вы должны передать любой локальный контекст, который вам нужен, в горутину.

JimB 06.02.2023 13:17
Создание API ввода вопросов на разных языках программирования (Python, PHP, Go и Node.js)
Создание API ввода вопросов на разных языках программирования (Python, PHP, Go и Node.js)
API ввода вопросов - это полезный инструмент для интеграции моделей машинного обучения, таких как ChatGPT, в приложения, требующие обработки...
0
1
56
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Go намеренно предпочитает не предоставлять идентификатор, так как это будет способствовать ухудшению программного обеспечения и нанесет ущерб всей экосистеме: https://go.dev/doc/faq#no_goroutine_id

Как правило, желание деанонимизировать горутины является недостатком дизайна и настоятельно не рекомендуется. Почти всегда будет гораздо лучший способ решить проблему. Например, если вам нужен уникальный идентификатор, его следует передать в функцию или, возможно, через context.Context.

Однако внутри среды выполнения требуются идентификаторы для реализации. В образовательных целях вы можете найти их с чем-то вроде:

package main

import (
    "bytes"
    "errors"
    "fmt"
    "runtime"
    "strconv"
)

func main() {
    fmt.Println(goid())

    done := make(chan struct{})
    go func() {
        fmt.Println(goid())
        done <- struct{}{}
    }()
    go func() {
        fmt.Println(goid())
        done <- struct{}{}
    }()
    <-done
    <-done
}

var (
    goroutinePrefix = []byte("goroutine ")
    errBadStack     = errors.New("invalid runtime.Stack output")
)

// This is terrible, slow, and should never be used.
func goid() (int, error) {
    buf := make([]byte, 32)
    n := runtime.Stack(buf, false)
    buf = buf[:n]
    // goroutine 1 [running]: ...

    buf, ok := bytes.CutPrefix(buf, goroutinePrefix)
    if !ok {
        return 0, errBadStack
    }

    i := bytes.IndexByte(buf, ' ')
    if i < 0 {
        return 0, errBadStack
    }

    return strconv.Atoi(string(buf[:i]))
}

Пример вывода:

1 <nil>
19 <nil>
18 <nil>

Их также можно найти (менее портативно) с помощью сборки, обратившись к полю goid в структуре g. Вот как обычно это делают такие пакеты, как github.com/petermattis/goid.

Другие вопросы по теме