SoFunction
Updated on 2025-03-04

How to get goroutine id in Go language

If you have used mainstream programming languages ​​that support concurrency such as Python and Java, you can usually get the ids of processes and threads more easily. However, in Go, there is no direct support for multi-process and multi-threading, but goroutine is provided to support concurrent programming. However, in Go, getting the id of goroutine is not as easy as other programming languages, but there is still a way. This article will introduce how to implement it.

Get the id of the current process

First of all, although Go does not provide multi-process programming, there will still be a process when starting Go programs. The Go standard library providesFunctions can easily obtain the id of the current process:

/jianghushinian/blog-go-example/blob/main/goroutine/id/pid/

package main

import (
	"fmt"
	"os"
)

func main() {
	// Get the id of the current process	pid := ()
	("process id:", pid)
}

Call()The pid (process id) of the current process will be returned.

Get the id of the current goroutine

Go does not directly provide a way to get the goroutine id, because the management of goroutine is handled by the Go runtime, and it does not expose the id of each goroutine. However, there are some ways to get indirect information related to goroutine.

Use the runtime package to get the goroutine id

Although we cannot directly obtain the id of each goroutine, we can pass it in disguisefunction to obtain.

The implementation code is as follows:

/jianghushinian/blog-go-example/blob/main/goroutine/id/

package main

import (
	"fmt"
	"runtime"
	"strconv"
	"strings"
	"sync"
)

func GoId() int {
	buf := make([]byte, 32)
	n := (buf, false)
	idField := ((string(buf[:n]), "goroutine "))[0]
	id, err := (idField)
	if err != nil {
		panic(("cannot get goroutine id: %v", err))
	}
	return id
}

func main() {
	("main", GoId())
	var wg 
	for i := 0; i < 10; i++ {
		i := i
		(1)
		go func() {
			defer ()
			(i, GoId())
		}()
	}
	()
}

This code is customizedGoIdfunction to get the id of the current goroutine andmainPrint their ids in the main goroutine and child goroutines of the function.

Let's explainGoIdImplementation of main logic of function:

1.(buf, false):

  • yesruntimeA public function provided by the package to obtain the stack information of the current goroutine.
  • parameterbufis a byte array used to store calls()Returned stack information.
  • The second parameter isfalse, means that we only get the stack information of the current goroutine, iftrueThis is to get the stack information of all goroutines.
  • ()The stack information of the current goroutine will be written tobufmiddle,nis the number of bytes returned, indicating the length of the stack information.

2.(string(buf[:n]), "goroutine "):

goroutine 1 [running]:
  • Convert stack information to string and remove prefixes"goroutine "
  • The first line format of the stack information is usually as follows:
  • Passed hereTrimPrefixRemove prefixes"goroutine "After that, the rest is the id of the goroutine and its status information.

3.idField := (...)[0]:

  • Will passTrimPrefixThe processed string is cut into a string slice by space.
  • Get the first field from the slice, this is the id of the goroutine, like1

If everything goes well,GoIdThe function finally returns the id of the current goroutine.

mainFunction implementation is relatively simple, call it firstGoId()Print the id of the main goroutine, then start the 10 sub goroutines and print their ids separately.

Execute the sample code and get the following output:

$ go run
main 1
9 29
0 20
5 25
6 26
7 27
8 28
2 22
1 21
4 24
3 23

In this way, we get the goroutine id by first obtaining the stack information and then parsing it from the stack information. I believe you can also find that this implementation method is not performing well, so don’t easily get the goroutine id unless it is absolutely necessary.

So is there a more efficient way?

Unfortunately, Go does not provide it. However, there is a third-party library that helps us realize it.

Use third-party libraries to get goroutine id

A more commonly used library is/petermattis/goid, can be used to get the id of the current goroutine.

Installation method:

$ go get /petermattis/goid

Example of usage:

/jianghushinian/blog-go-example/blob/main/goroutine/id/goid/

package main

import (
	"fmt"
	"sync"

	"/petermattis/goid"
)

func main() {
	("main", ())
	var wg 
	for i := 0; i < 10; i++ {
		i := i
		(1)
		go func() {
			defer ()
			(i, ())
		}()
	}
	()
}

Execute the sample code and get the following output:

$ go run goid/
main 1
9 43
4 38
5 39
6 40
7 41
8 42
1 35
0 34
2 36
3 37

We only need to call()You can get the id of the current goroutine.

goidThe library uses C and assembly to get the goroutine id, so the performance is better. andgoidAll Go versions are compatible. As can be seen from the project file name, different Go versions have different implementations:

$ tree goid
goid
├── LICENSE
├── 
├── 
├── 
├── goid_gccgo.go
├── goid_go1.
├── goid_go1.
├── goid_go1.
├── goid_go1.
├── goid_go1.
├── goid_go1.
├── goid_slow.go
├── goid_test.go
├── runtime_gccgo_go1.
├── runtime_go1.
├── runtime_go1.
├── runtime_go1.
└── runtime_go1.

1 directory, 18 files

existgoid_go1.You can see that the implementation of the C language version is as follows:

/petermattis/goid/blob/master/goid_go1.

// +build !go1.4

#include <>

void ·Get(int64 ret) {
    ret = g->goid;
    USED(&ret);
}

existgoid_go1.You can see that the assembly language version is implemented as follows:

/petermattis/goid/blob/master/goid_go1.

// +build amd64 amd64p32 arm 386
// +build go1.4,!go1.5

#include ""

#ifdef GOARCH_arm
#define JMP B
#endif

TEXT ·getg(SB),NOSPLIT,$0-0
	JMP	runtime·getg(SB)

In addition, in order to ensure compatibility,There is also a Go language version implementation:

/petermattis/goid/blob/master/

package goid

import (
	"bytes"
	"runtime"
	"strconv"
)

func ExtractGID(s []byte) int64 {
	s = s[len("goroutine "):]
	s = s[:(s, ' ')]
	gid, _ := (string(s), 10, 64)
	return gid
}

// Parse the goid from () output. Slow, but it works.
func getSlow() int64 {
	var buf [64]byte
	return ExtractGID(buf[:(buf[:], false)])
}

Here the implementation of Go version is also used(), and the comments also indicate that this implementation is slower.

So, if we really need to get the id of goroutine, it is recommended to use itgoid

Summarize

Get the id of the current process in Go and you can use it()function. It is more difficult to obtain the current goroutine id. The Go standard library does not directly provide this function, but we can use it in disguise.()The returned stack information can also be obtained from the third-party library.goidCome to get it.

The above is the detailed content of how to obtain goroutine id in Go. For more information about Go obtaining goroutine id, please follow my other related articles!