problem with generic type switch

255 views
Skip to first unread message

Xiangrong Fang

unread,
Apr 8, 2024, 5:03:34 AM4/8/24
to golang-nuts
I wrote a TLV handling package: go.xrfang.cn/tlv, and encountered problem with type checking.  Problematic code below:

1.  The "Set" function in side tlv package:

package tlv

type (
    ValueType interface {
        string | []byte | ~float32 | ~float64 |
        ~int8 | ~int16 | ~int32 | ~int64 |
        ~uint8 | ~uint16 | ~uint32 | ~uint64
    }
    Prop map[byte][]byte
)

func Set[T ValueType](p Prop, tag byte, val T) Prop {
    ... ...
    switch v := any(val).(type) {
    case string:
    ... ...
    default:
        fmt.Printf("tlv.Set: '%T' not supported!\n", val) 
    }
    ...
}

2. event.go, which uses tlv:

package event

import (
"go.xrfang.cn/tlv"
)

type (
Class byte
Event struct {
tlv.Prop
}
)

const (
TagClass  = 3
)

func (e *Event) WithClass(cls Class) *Event {
(*e).Prop = tlv.Set((*e).Prop, TagClass, cls)
return e
}

The problem is, while the Class type is based on "byte", it should be accepted by tlv.Set(), which is the case (there is no compiler error).  But when the code is running, it printed error message: tlv.Set: 'event.Class' not supported!

Axel Wagner

unread,
Apr 8, 2024, 6:35:18 AM4/8/24
to Xiangrong Fang, golang-nuts
Yes, the *underlying type* of Class is `byte`, but the type-switch checks if the dynamic type is *exactly* `byte`.
The only way, currently, to implement the kind of check you want is to use reflect:

switch rv := reflect.ValueOf(v); rv.Kind() {
case reflect.Uint8: // byte
    v := uint8(rv.Uint())
// ...
}

Though you might be interested in #45380, which would be able to solve this without reflect.

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/b4786988-b9da-44c3-9070-ba718f3be5ban%40googlegroups.com.

Xiangrong Fang

unread,
Apr 9, 2024, 9:04:09 PM4/9/24
to golang-nuts

Thank you for the info.  The purpose of using generics is to avoid reflect or interface{}, at least for me :-)
Reply all
Reply to author
Forward
0 new messages