As we know in go, a thread may be created when the goroutine has to perform a blocking call, such as a system call, or a call to a C library via cgo. Some test code:
I altered your program slightly to output a much bigger block
package main
import (
"io/ioutil"
"os"
"runtime"
"strconv"
)
func main() {
runtime.GOMAXPROCS(2)
data := make([]byte, 128*1024*1024)
for i := 0; i < 200; i++ {
go func(n int) {
for {
err := ioutil.WriteFile("testxxx"+strconv.Itoa(n), []byte(data), os.ModePerm)
if err != nil {
println(err)
break
}
}
}(i)
}
select {}
}
This then shows >200 threads as you expected
$ cat /proc/17033/status | grep -i thread
Threads: 203
So I think the syscalls were exiting too quickly in your original test to show the effect you were expecting.