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.