Skip to content

Instantly share code, notes, and snippets.

@winebarrel
Last active October 5, 2024 02:14
Show Gist options
  • Save winebarrel/83ea48dbd7017cfbeb82c8b766945e91 to your computer and use it in GitHub Desktop.
Save winebarrel/83ea48dbd7017cfbeb82c8b766945e91 to your computer and use it in GitHub Desktop.
contextがキャンセルされたときに*sql.Connが無効になるかの検証
% go version
go version go1.23.0 darwin/arm64
% grep mysql go.mod
github.com/go-sql-driver/mysql v1.8.1 // indirect
% go run main.go
n1: 0
n1: 0
[mysql] 2024/10/05 11:02:35 connection.go:49: invalid connection
2024/10/05 11:02:35 QueryRowContext failed (n2): driver: bad connection
exit status 1
package main
import (
"context"
"database/sql"
"errors"
"fmt"
"log"
"time"
_ "github.com/go-sql-driver/mysql"
)
func run(ctx context.Context, db *sql.DB) error {
db.PingContext(ctx)
conn, err := db.Conn(context.TODO()) // *sql.Connの生成時にはcontextを渡さない
if err != nil {
return err
}
defer conn.Close()
for range 10 {
var n1 int
err = conn.QueryRowContext(ctx, "select sleep(1)").Scan(&n1)
if err != nil {
if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) {
break
} else {
return fmt.Errorf("QueryRowContext failed (n1): %w", err)
}
}
fmt.Println("n1:", n1)
}
var n2 int
err = conn.QueryRowContext(ctx, "select 2").Scan(&n2)
if err != nil {
return fmt.Errorf("QueryRowContext failed (n2): %w", err)
}
fmt.Println("n2:", n2)
return nil
}
func main() {
db, err := sql.Open("mysql", "root@tcp(localhost:13306)/mysql")
if err != nil {
log.Fatal(err)
}
defer db.Close()
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
err = run(ctx, db)
if err != nil {
log.Fatal(err)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment