通过引用设置接口{}参数

通过引用设置接口{}参数,第1张

通过引用设置接口{}参数

您可以使用来模拟AppEngine数据存储接口

reflect
。通常,我说的是最小化反射,但是您(以及AppEngine和其他ORM)在这里没有其他很好的选择来展示您想要的接口。对于模仿
Get
您的内容:

  • 得到
    reflect.Value
    ValueOf()
  • 获得您想要创建的事物的类型
  • 用它创建
    reflect.Zero
  • (可选)使用
    reflect.Field()
    ,填充一些数据。
  • 使用
    reflect.Indirect()
    Value.Set()
    通过指针设置原稿。

一个仅通过指针将结构归零的简单示例位于http://play.golang.org/p/g7dNlrG_vr,并在此处复制:

package mainimport (    "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 mainimport (    "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))    }}

在实时代码中(相对于像您那样进行测试),使用类型开关(如Martin所建议的)会更快,以便为每种类型运行专用的本机代码。如果您在类型上有不同的行为,那也可能会很方便。为一个例子

GetMulti
是在http://play.golang.org/p/q-9WyUqv6P及以下:

package mainimport "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具有指针,以及其他类型,例如包含指向数据的指针的切片。其中有没有意义“通过引用传递”仅仅是围棋永远不会改变的值参数(

int
struct
)为指针含蓄。C
参考参数完全做到了这一点:C 在调用方中
void f(i int&) { i++;}
发生更改
i
,而调用方没有在调用站点上显式传递指针。
func (i int) { i++ }
不。

在Go中,您可以查看传递给函数调用的类型,并告诉它可以更改哪些数据。使用C ++参考参数或某些语言的“按引用传递”语义, 任何
调用都可能会更改本地变量。您不能不查找声明就知道。

为了避免不必要的数据复制,在slice,字符串,映射,接口和通道值的实现中已经有指针。在这些类型中,指针,切片和映射实际上将允许您通过它们修改数据。同样,像在C
++中一样,Go的

this
-like接收器参数可以是一个指针,而
&
调用代码中没有明确的指示。在Russ
Cox的godata帖子中。



欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5560264.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-14
下一篇 2022-12-14

发表评论

登录后才能评论

评论列表(0条)

保存