Why does the behavior of chan change after I use gorm to connect to the database

Viewed 32

A normal example is this:

package main

import (
    "fmt"
    "time"
)

func main() {
    ch := make(chan int)
    func() {
        time.Sleep(1)
        ch <- 1
    }()

    fmt.Println(<-ch)
}

The output should be:

# go run test.go
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send]:
main.main.func1(...)
    /root/test.go:17
main.main()
    /root/test.go:18 +0x47
exit status 2

But when I add the code to connect to the database like this:

package main

import (
    "fmt"
    "time"

    "gorm.io/driver/mysql"
    "gorm.io/gorm"
)

func main() {
    db, err := gorm.Open(mysql.Open("dsn"))
    fmt.Printf("%v, %s\n", db, err)

    ch := make(chan int)
    func() {
        time.Sleep(1)
        ch <- 1
    }()

    fmt.Println(<-ch)
}

It doesn't report an error, it keeps blocking, the output is(I ended it with ctrl+c):

# go run test.go
&{0xc00015c510 <nil> 0 0xc00016c380 1}, %!s(<nil>)
^Csignal: interrupt

Can anyone help me, thanks.

1 Answers

It does not report all goroutines are asleep in case of connected DB because all goroutines are not asleep.

gorm and db start their own goroutines that are waiting to send receive, doing other stuff.

if you do a ctrl+\ in both cases these goroutines will be shown

1 No DB connected

goroutine 0 [idle]: runtime.epollwait()
        /usr/lib/golang/src/runtime/sys_linux_amd64.s:699 +0x20 runtime.netpoll(0xc000032500?)
        /usr/lib/golang/src/runtime/netpoll_epoll.go:126 +0xdc
  1. DB connected
goroutine 0 [idle]:
runtime.futex()
        /usr/lib/golang/src/runtime/sys_linux_amd64.s:552 +0x21
runtime.futexsleep(0x10000000000?, 0xcb927f8?, 0x7fffc45f8fa8?)
        /usr/lib/golang/src/runtime/os_linux.go:66 +0x36

goroutine 1 [chan send]:
main.main.func1(...)

goroutine 19 [select]:
database/sql.(*DB).connectionOpener(0xc00019ea90, {0x81af60, 0xc0001972c0})

goroutine 20 [select]:
github.com/go-sql-driver/mysql.(*mysqlConn).startWatcher.func1()
Related