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.