Go version

go version go1.24.2 darwin/arm64

Output of go env in your module/workspace:

Not relevant

What did you do?

I ran the example: https://go.dev/play/p/ay6-djssQwi with both go versions (1.23, 1.24).

package main

import (
    "database/sql"
    "fmt"
)

func main() {
    v := sql.Null[int32]{V: 42, Valid: true}
    value, err := v.Value()
    fmt.Printf("%T, %v\n", value, err)
}

What did you see happen?

With go version 1.24, the return type from Value() method is int64 instead of it being int32.

int64, <nil>

With go version 1.23, its working as expected and the return type from Value() method is int32.

int32, <nil>

What did you expect to see?

I am expecting to see int32 type as the type parameter passed to sql.Null is int32.

int32, <nil>

On looking the implementation I see a recent change in Value method for Null[T any] type.

In go version 1.23.9: https://github.com/golang/go/blob/f77084d15d53e6aa09d2e7f867e69cc9766da2c5/src/database/sql/sql.go#L431

func (n Null[T]) Value() (driver.Value, error) {
    if !n.Valid {
        return nil, nil
    }
    return n.V, nil
}

In go version 1.24: https://github.com/golang/go/blob/431f75a0b9890faa2b6a5ade8e19d4c23d0aaaf0/src/database/sql/sql.go#L429

func (n Null[T]) Value() (driver.Value, error) {
    if !n.Valid {
        return nil, nil
    }
    v := any(n.V)
    // See issue 69728.
    if valuer, ok := v.(driver.Valuer); ok {
        val, err := callValuerValue(valuer)
        if err != nil {
            return val, err
        }
        v = val
    }
    // See issue 69837.
    return driver.DefaultParameterConverter.ConvertValue(v)
}

Upon checking further, noticed that driver.DefaultParameterConverter.ConvertValue(v) is the culprit here as this method will always return int64 for any signed int type because of

    case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
        return rv.Int(), nil

Comment From: gabyhelp

Related Issues

(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)

Comment From: seankhliao

I believe the new behaviour is correct: driver.Value only lists int64 as a supported type https://pkg.go.dev/database/sql/driver#Value

Note that there's an Int32 converter that converts int32 into int64 https://pkg.go.dev/database/sql/driver#Int32

Comment From: mahendrabishnoi2

I believe the new behaviour is correct: driver.Value only lists int64 as a supported type https://pkg.go.dev/database/sql/driver#Value

Note that there's an Int32 converter that converts int32 into int64 https://pkg.go.dev/database/sql/driver#Int32

In that case, shouldn't there be a type constraint on this type instead of allowing any? I'm not sure if that's doable or not.

Comment From: mahendrabishnoi2

I believe the new behaviour is correct: driver.Value only lists int64 as a supported type https://pkg.go.dev/database/sql/driver#Value

Note that there's an Int32 converter that converts int32 into int64 https://pkg.go.dev/database/sql/driver#Int32

In that case, shouldn't there be a type constraint on this type instead of allowing any? I'm not sure if that's doable or not.

Ping @seankhliao