I'd suggest simply
func (b *Binlog) writeArgumentToOutput(writer writer, arg uint64) error {
/* do the writing */ }
and doing the actual conversions at the call-site. It's type-safe, shorter,
faster and more idiomatic - with the tiny downside of a `uint64()` here and
there.

Alternatively, use reflect as it's intended to - something like
func writeArgumentToOutput(writer writer, arg interface{}) error {
    rv := reflect.ValueOf(arg)
    var v uint64
    if k := rv.Kind(); k >= reflect.Int && k < reflect.Uint {
        v = uint64(rv.Int())
    } else if k <= reflect.Uintptr {
        v = rv.Uint()
    } else {
        return fmt.Errorf("Unsupported type: %T\n", reflect.TypeOf(arg))
    }
    /* write v */
    return nil
}

this is probably a bit slower than the above, type-safe version, but
probably not noticeably slower than the unsafe large type-switch above and
has the benefit of also not needing conversion at the call-site (it also
works correctly with all integer types, which the type-switch doesn't).

But in the end, any slowness here comes from passing things as an
interface{}, instead of just as a value. You can't really optimize that
away, because it's inherent in the approach.

On Sun, Nov 25, 2018 at 5:32 PM Michel Levieux <m.levi...@capitaldata.fr>
wrote:

> No offense intended, but that code is wrong on so many levels...
>
>
> I strongly believe you that you are not trying to offend anyone, but this
> question is interesting for me too, and I'd like more details. Could you
> please explain, from worst to "less worst", what's wrong with this code?
> Reflection is sometimes really misleading for people who don't have a deep
> understanding of the compiler, and such pieces of code exist all around the
> internet. Would you give us a more precise feedback?
>
> Thanks in advance!
>
> Le dim. 25 nov. 2018 à 17:17, Jan Mercl <0xj...@gmail.com> a écrit :
>
>> No offense intended, but that code is wrong on so many levels...
>>
>> On Sun, Nov 25, 2018, 17:10 <lary...@gmail.com> wrote:
>>
>>> The code below consumes ~40% of the total execution time. According to
>>> the profiler i := uint64(arg.(uint32)) is a major contributor
>>>
>>> // Cast the integer argument to uint64 and call a "writer"
>>> // The "writer" knows how many bytes to add to the binary stream
>>> // Type casts from interface{} to integer consume 40% of the overall
>>> // time. Can I do better? What is interface{} in Golang?
>>> func (b *Binlog) writeArgumentToOutput(writer writer, arg interface{},
>>> argKind reflect.Kind) error {
>>>     // unsafe pointer to the data depends on the data type
>>>     var err error
>>>     switch argKind {
>>>     case reflect.Int8:
>>>         i := uint64(arg.(int8))
>>>         err = writer.write(b.ioWriter, unsafe.Pointer(&i))
>>>     case reflect.Int16:
>>>         i := uint64(arg.(int16))
>>>         err = writer.write(b.ioWriter, unsafe.Pointer(&i))
>>>     case reflect.Int32:
>>>         i := uint64(arg.(int32))
>>>         err = writer.write(b.ioWriter, unsafe.Pointer(&i))
>>>     case reflect.Int64:
>>>         i := uint64(arg.(int64))
>>>         err = writer.write(b.ioWriter, unsafe.Pointer(&i))
>>>     case reflect.Uint8:
>>>         i := uint64(arg.(uint8))
>>>         err = writer.write(b.ioWriter, unsafe.Pointer(&i))
>>>     case reflect.Uint16:
>>>         i := uint64(arg.(uint16))
>>>         err = writer.write(b.ioWriter, unsafe.Pointer(&i))
>>>     case reflect.Uint32:
>>>         i := uint64(arg.(uint32))
>>>         err = writer.write(b.ioWriter, unsafe.Pointer(&i))
>>>     case reflect.Uint64:
>>>         i := uint64(arg.(uint64))
>>>         err = writer.write(b.ioWriter, unsafe.Pointer(&i))
>>>     case reflect.Int:
>>>         i := uint64(arg.(int))
>>>         err = writer.write(b.ioWriter, unsafe.Pointer(&i))
>>>     case reflect.Uint:
>>>         i := uint64(arg.(uint))
>>>         err = writer.write(b.ioWriter, unsafe.Pointer(&i))
>>>     default:
>>>         return fmt.Errorf("Unsupported type: %T\n", reflect.TypeOf(arg))
>>>     }
>>>     return err
>>> }
>>>
>>>
>>> --
>>> 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+unsubscr...@googlegroups.com.
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>> --
>>
>> -j
>>
>> --
>> 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+unsubscr...@googlegroups.com.
>> For more options, visit https://groups.google.com/d/optout.
>>
> --
> 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+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
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+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to