On Tue, Aug 1, 2017 at 11:44 AM, roger peppe <rogpe...@gmail.com> wrote:

> On 1 August 2017 at 13:57, Josh Humphries <jh...@bluegosling.com> wrote:
> > Although that solution creates a heap-allocated tmp for every element in
> the
> > slice. Using an interface, the value will be inlined instead of
> > heap-allocated if it fits without boxing (so most primitive types and
> > pointer types won't need heap allocation).
>
> As it happens, it's the other way round - the solution using Interface can
> make an allocation per element, but the solution using Value does not.
>

The solution using Value is calling reflect.New inside the loop. Why do you
say that it does not make an allocation per element?

Also, I'm not sure I follow that using Interface makes an allocation per
element. My understanding is that the actual value can be stored in the
interface value if it is small enough (1 or 2 words?). So boxing primitives
and pointers should generally store the value in the interface tuple (which
itself is stack allocated) as opposed to allocating heap space for it and
storing a pointer.

For larger types (e.g. structs beyond a certain size) it will indeed
allocate on the heap. I don't see any simple way around this. There may be
some clever tricks, possibly involving cgo or asm, to avoid it though
(maybe like how reflect.Swapper
<https://golang.org/src/reflect/swapper.go?s=337:383#L3> works, although it
also heap allocates for values >8 bytes).



>
> https://play.golang.org/p/Q0VHbfL7Ij
>
> Additionally, the solution using Interface can lose the type information
> in some cases and panic as a result.
>


A simple guard for the nil case is necessary to prevent the panic (since
the nil interface results in an invalid reflect.Value):

tmp := a.Interface()
var tmprv reflect.Value
if tmp == nil {
  tmprv = reflect.Zero(a.Type())
} else {
  tmprv = reflect.ValueOf(tmp)
}
a.Set(b)
b.Set(tmprv)


>
> https://play.golang.org/p/WocF9CaPoR
>
>   cheers,
>     rog.
>
>
> >
> > ----
> > Josh Humphries
> > jh...@bluegosling.com
> >
> > On Tue, Aug 1, 2017 at 7:29 AM, roger peppe <rogpe...@gmail.com> wrote:
> >>
> >> FWIW, you don't have to use Interface to do the swap:
> >>
> >> https://play.golang.org/p/O8lGJGGOXP
> >>
> >> On 31 July 2017 at 15:18, eZio Pan <eziopa...@gmail.com> wrote:
> >> > Hello,
> >> > I want to build a "universal slice reverser" with reflect.MakeFunc.
> But
> >> > I
> >> > don't know how to get a copy of reflect.Value's underlying value,
> which
> >> > make
> >> > result not correct.
> >> >
> >> > Here is the code:
> >> >
> >> > package main
> >> >
> >> > import (
> >> > "fmt"
> >> > "reflect"
> >> > )
> >> >
> >> > func reverse(in []reflect.Value) (out []reflect.Value) {
> >> > inls := in[0]
> >> > inlslen := inls.Len()
> >> >
> >> > for i, j := 0, inlslen-1; i < j; i, j = i+1, j-1 {
> >> > a := inls.Index(i)
> >> > b := inls.Index(j)
> >> > // how to get underlying value of a and b ?
> >> > a.Set(b)
> >> > b.Set(a)
> >> > }
> >> > return in
> >> > }
> >> >
> >> > var intFlipper func([]int) []int
> >> >
> >> > func main() {
> >> > emptyFunc := reflect.ValueOf(&intFlipper).Elem()
> >> > pseudoFunc := reflect.MakeFunc(emptyFunc.Type(), reverse)
> >> > emptyFunc.Set(pseudoFunc)
> >> > fmt.Printf("%v\n", intFlipper([]int{2, 3, 4, 5, 6, 7}))
> >> > }
> >> >
> >> > My code return [7 6 5 5 6 7], but excepting result is [7 6 5 4 3 2]
> >> >
> >> > --
> >> > 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