首先,
interface{}类型只是接受所有值的类型,因为它是带有空方法集的接口,并且每种类型都可以满足该要求。
int例如没有任何方法,也没有
interface{}。
对于交换两个变量的值的方法,首先需要确保这些变量实际上是可修改的。传递给函数的值始终会被复制(切片和映射之类的引用类型除外,但这不是我们当前关注的问题)。您可以通过使用指向变量的指针来实现可修改的参数。
因此,有了这些知识,您就可以
SwapNum像下面这样定义:
func SwapNum(a interface{}, b interface{})
现在
SwapNum是一个接受两个任何类型参数的函数。你不会写
func SwapNum(a *interface{}, b *interface{})
因为这将只接受类型的参数,
*interface{}而不是任何类型的参数。(在这里自己尝试)。
因此,我们有一个签名,剩下的唯一事情就是交换值。
func SwapNum(a interface{}, b interface{}) { *a, *b = *b, *a}
不,这将 无法
正常工作。通过使用,
interface{}我们必须执行运行时类型声明来检查我们是否在做正确的事情。因此,必须使用该
reflect软件包扩展代码。如果您不了解反射,本文可能会让您入门。
基本上,我们将需要以下功能:
func SwapNum(a interface{}, b interface{}) { ra := reflect.ValueOf(a).Elem() rb := reflect.ValueOf(b).Elem() tmp := ra.Interface() ra.Set(rb) rb.Set(reflect.ValueOf(tmp))}
该代码反映
a并
b使用
reflect.ValueOf()了我们可以对其进行检查的代码。在同一行中,我们假设我们有指针值并通过调用它们来取消引用
.Elem()它们。
这基本上转化为
ra := *a和
rb :=*b。之后,我们
*a通过使用
.Interface()
并分配值(有效地制作副本)来请求的副本。
最后,我们使用] 5设置
ato 的值,该值转换为
然后分配给,我们将其存储在temp中。变量之前。为此,我们需要转换回自身的反射,以便可以使用它(将a
作为参数)。
b``[ra.Set(rb)
*a =*b``b``a``tmp``rb.Set()``reflect.Value我们可以做得更好吗?
是!
我们可以使用来使代码更安全,或者更好地使
Swap类型的定义安全
reflect.MakeFunc。在文档中(跟随链接)是一个示例,非常类似于您尝试的示例。本质上,您可以使用反射将内容填充到函数原型中。当您提供函数的原型(签名)时,编译器可以检查类型,将值减小为时无法检查类型
interface{}。
用法示例:
var intSwap func(*int, *int)a,b := 1, 0makeSwap(&intSwap)intSwap(&a, &b)// a is now 0, b is now 1
其背后的代码:
swap := func(in []reflect.Value) []reflect.Value { ra := in[0].Elem() rb := in[1].Elem() tmp := ra.Interface() ra.Set(rb) rb.Set(reflect.ValueOf(tmp)) return nil}makeSwap := func(fptr interface{}) { fn := reflect.ValueOf(fptr).Elem() v := reflect.MakeFunc(fn.Type(), swap) fn.Set(v)}
的代码与的代码
swap基本相同
SwapNum。
makeSwap与文档中使用的相同,说明得很好。
免责声明:
上面的代码对给定的值和值的外观进行了许多假设。通常,例如,您需要检查给定的值
SwapNum实际上是指针值,依此类推。为了清楚起见,我将其省略。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)