Interface setup {} Parameter by reference

I find it difficult to understand how to set the value of an interface that was passed as a pointer. I am trying to do something according to this:

import "fmt"

var Stuff map[string]interface{}

func main() {
    var num int
    Stuff["key"] = 9001
    get("key", &num)
    fmt.Println("num:", num)
}

func get(k string, v interface{}) {
    *v = Stuff[k]
}

What do I need to do to make my program exit

num: 9001

Edit: Is there a possible catch-all solution with reflect?

+4
source share
5 answers

You can emulate the AppEngine datastore interface with reflect; I usually say minimize reflection, but you (and AppEngine and other ORMs) have no other great option to present the interface you want. For something emulating Getyou:

  • get reflect.ValuewithValueOf()
  • ,
  • reflect.Zero
  • reflect.Field() ..
  • reflect.Indirect() Value.Set(), .

, , http://play.golang.org/p/g7dNlrG_vr :

package main

import (
    "fmt"
    "reflect"
)

func main() {
    i := 1
    clear(&i)
    fmt.Println(i)
}

func clear(dst interface{}) {
    // ValueOf to enter reflect-land
    dstPtrValue := reflect.ValueOf(dst)
    // need the type to create a value
    dstPtrType := dstPtrValue.Type()
    // *T -> T, crashes if not a ptr
    dstType := dstPtrType.Elem()
    // the *dst in *dst = zero
    dstValue := reflect.Indirect(dstPtrValue)
    // the zero in *dst = zero
    zeroValue := reflect.Zero(dstType)
    // the = in *dst = 0
    dstValue.Set(zeroValue)
}

GetMulti . : http://play.golang.org/p/G_6jit2t-2 :

package main

import (
    "fmt"
    "reflect"
)

func main() {
    s := []int{}
    getMultiZeroes(&s, 10)
    fmt.Println(s)
}

func getMultiZeroes(slicePtrIface interface{}, howMany int) {
    // enter `reflect`-land
    slicePtrValue := reflect.ValueOf(slicePtrIface)
    // get the type
    slicePtrType := slicePtrValue.Type()
    // navigate from `*[]T` to `T`
    sliceElemType := slicePtrType.Elem().Elem() // crashes if input type not `*[]T`
    // we'll need this to Append() to
    sliceValue := reflect.Indirect(slicePtrValue)
    // and this to Append()
    sliceElemValue := reflect.Zero(sliceElemType)

    // append requested number of zeroes
    for i := 0; i < howMany; i++ {
        // s := append(s, v)
        sliceValue.Set(reflect.Append(sliceValue, sliceElemValue))
    }
}

( , ), ( ), ; , . GetMulti http://play.golang.org/p/q-9WyUqv6P :

package main

import "fmt"

func main() {
    s := []int{}
    getZeroes(&s)
    fmt.Println(s)

    fails := []float32{}
    getZeroes(&fails)
}

func getZeroes(slicePtrIface interface{}) {
    switch sp := slicePtrIface.(type) {
    case *[]int:
        (*sp) = append((*sp), 0, 0)
    case *[]string:
        (*sp) = append((*sp), "", "")
    default:
        panic(fmt.Sprintf("getZeroes: passed type %T, which is not a pointer to a slice of a supported type", slicePtrIface))
    }
}

; reflect . http://play.golang.org/p/6qw52B7eC3 ( , ).

, , GetMulti, GetMulti, .


, :

" " , . Go , , . , " ", , Go (int, struct) . ++ : ++ void f(i int&) { i++; } i , callsite. func (i int) { i++ } .

Go , , , . ++ " " ; , .

, , , , . , . , ++, Go this - & . Russ Cox godata post , .

+8

Go

Calls

. , . , .

Go ; . . ,

package main

import "fmt"

var Stuff map[string]interface{}

func main() {
    Stuff = make(map[string]interface{})
    Stuff["key"] = 9001
    var value interface{}
    get("key", &value)
    num := value.(int)
    fmt.Println("num:", num)
}

func get(k string, v interface{}) {
    *v.(*interface{}) = Stuff[k]
}

:

num: 9001
+3

-: " " Go. . , , . , Go .

: , (, ), ( ).

: (.. ) . ( ", Go " ) .

: interface{}, - . , - () ?

, - .

func main() {
    var num int
    Stuff["key"] = 9001
    num = get("key").(int)
}
func get(k string) interface{}{
    return Stuff[k]
}
+1

Martin Gallagher's solution works fine, but he said you can't use generics in Golang, so the code looks a little ugly. I assume that another solution is to always use interface{}as a type, and then use (or check the type) in your program. Something like this: http://play.golang.org/p/0o20jToXHV

+1
source

http://play.golang.org/p/kx5HvEiOm9

Without generics, you will have to implement the {} switch for each of your supported types.

0
source

All Articles