Select on chan read from a func never calls the func
Author: pancstaCreated Jul 8, 2026Updated Jul 8, 2026
The following program sample.go triggers an unexpected result
package main
import (
"reflect"
// _ "github.com/dominikbraun/graph"
"github.com/traefik/yaegi/interp"
"github.com/traefik/yaegi/stdlib"
symhelpers "tb/protos/dyn_handlers/symbols"
)
func main() {
// lock-free critical section
Eval(`
dynEnd := make(chan struct{})
newRandCh := func(i int) chan bool {
fmt.Println("newRandCh")
ch := make(chan bool)
go func(){
time.Sleep(time.Duration(i) * time.Second)
ch <- true
}()
return ch
}
ret := func() bool {
fmt.Println("eval start")
go func() {
i := 0
for {
fmt.Println("eval loop")
select {
case v, ok := <-newRandCh(1):
fmt.Println("newRandCh", v, ok)
close(dynEnd)
case v, ok := <-newRandCh(2):
fmt.Println("newRandCh", v, ok)
close(dynEnd)
}
// time.Sleep(time.Second)
// i++
// if i > 10 {
// close(dynEnd)
// fmt.Println("loop end")
// return
// }
}
}()
return true
}()
close(end)
<-dynEnd
ret
`)
select{}
}
func Eval(code string) bool {
i := interp.New(interp.Options{})
if err := i.Use(stdlib.Symbols); err != nil {
panic(err)
}
end := make(chan struct{})
i.Use(symhelpers.Symbols)
i.Use(interp.Exports{
"main/main": map[string]reflect.Value{
"end": reflect.ValueOf(end),
},
})
// required import
_, err := i.Eval(`import (
. "main"
// stdlib deps
"fmt"
"time"
)
`)
if err != nil {
panic(err)
}
go func() {
_, err := i.Eval(code)
if err != nil {
panic(err)
}
}()
<-end
return true
}Expected result
eval start
eval loop
newRandChGot
eval start
eval loopYaegi Version
v0.16.1
Additional Notes
Channels have to initialized before the select statement, like so:
ch1 := newRandCh(1)
select {
case v, ok := <-ch1:
fmt.Println("newRandCh", v, ok)
close(dynEnd)
case v, ok := <-newRandCh(2):
fmt.Println("newRandCh", v, ok)
close(dynEnd)
}Source: traefik/yaegi