- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我想使用接口(interface)交换两个数字,但接口(interface)的概念让我很困惑。
http://play.golang.org/p/qhwyxMRj-c
这是代码和 Playground 。如何使用界面并交换两个输入数字?我需要定义两个结构吗?
type num struct {
value interface{}
}
type numbers struct {
b *num
c *num
}
func (a *num) SwapNum(var1, var2 interface{}) {
var a num
temp := var1
var1 = var2
var2 = temp
}
func main() {
a := 1
b := 2
c := 3.5
d := 5.5
SwapNum(a, b)
fmt.Println(a, b) // 2 1
SwapNum(c, d)
fmt.Println(c, d) // 5.5 3.5
}
最佳答案
首先,interface{}
类型只是一种接受所有值的类型,因为它是一个具有空方法集的接口(interface),并且每种类型都可以满足这一点。例如,int
没有任何方法,interface{}
也没有。
对于交换两个变量值的方法,您首先需要确保这些变量实际上是可修改的。传递给函数的值总是被复制(除了像 slice 和映射这样的引用类型,但这不是我们目前关心的)。您可以通过使用指向变量的指针来实现可修改的参数。
因此,有了这些知识,您可以继续定义 SwapNum
,如下所示:
func SwapNum(a interface{}, b interface{})
现在 SwapNum
是一个接受两个任意类型参数的函数。你不能写
func SwapNum(a *interface{}, b *interface{})
因为这只接受 *interface{}
类型的参数,而不仅仅是任何类型。(亲自尝试 here )。
所以我们有一个签名,唯一剩下的就是交换值。
func SwapNum(a interface{}, b interface{}) {
*a, *b = *b, *a
}
不,这不会那样工作。通过使用 interface{}
,我们必须执行运行时类型断言来检查我们是否在做正确的事情。因此必须使用 reflect
包扩展代码。 This article如果您不了解反射,可能会让您入门。
基本上我们需要这个函数:
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))
}
此代码使用 reflect.ValueOf()
反射(reflect)了 a
和 b
这样我们就可以检查它。在同一行中,我们假设我们有指针值和取消引用他们通过调用 .Elem()
在他们身上。
这基本上转换为 ra := *a
和 rb := *b
。之后,我们通过使用 .Interface()
请求值来制作 *a
的副本。并分配它(有效地制作副本)。
最后,我们使用[ra.Set(rb)
] 5 将a
的值设置为b
,转换为 *a = *b
然后将 b
分配给我们存储在 temp 中的 a
。变前。为了这,我们需要将 tmp
转换回自身的反射,以便可以使用 rb.Set()
(它需要一个 reflect.Value
作为参数)。
是的!我们可以使代码更加类型安全,或者更好的是,使 Swap
的定义类型安全通过使用 reflect.MakeFunc
.在文档中(点击链接)是一个非常有用的例子就像你正在尝试的那样。本质上你可以用内容填充函数原型(prototype)通过使用反射。当您提供函数的原型(prototype)(签名)时编译器可以检查类型,当值被缩减为 interface{}
时它不能检查。
示例用法:
var intSwap func(*int, *int)
a,b := 1, 0
makeSwap(&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
是一样的作为文档中使用的那个,解释得很好。
免责声明:上面的代码对给定的内容做了很多假设,值(value)观是什么样的。通常你需要检查,例如,给定的SwapNum
的值实际上是指针值等等。我把它留给了清晰的原因。
关于戈朗 : interface to swap two numbers,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19301742/
我想知道将任何数据发送到模板(html/template 包)的真正方法是什么?我的代码如下: var templates = template.Must(template.ParseFiles(
我有密码 if config.Process.TraceLog != "" { f, err := os.OpenFile(config.Process.TraceLog, os.O_RDWR
大家好。我是 GO 的新手,需要一些帮助。我有一个具有这种结构的项目 但让我们假设我的逻辑包 中有 100500 个项目。如果我只需要为特定包导入一个或两个文件怎么办?我可以这样做还是只能导入完整包?
package main import ( "fmt" ) func main() { var square int box := [4]int{1, -2, 3, 4}
我想在每个范围循环后递增一个变量。但是,似乎无法使用标准(for init; condition; post {})语法,因此我想知道为什么。这是我正在尝试做的事情 for item := r
这个问题在这里已经有了答案: Creating a Constant Type and Restricting the Type's Values (2 个答案) 关闭 6 年前。 什么是只允许一组
我试过编译我的简单程序: func main(){fmt.Printf("Hello")} 根据文档在我的 PC 上使用 64 位 Debian Linux 到 MIPS 架构 https://gol
为什么不在 channel 上发送并阻止执行?我怎样才能使这个星座工作,以便我可以向 MoneyDive() 发送信号并继续执行? package main import ( "fmt" )
这是来自 Golang.org http://golang.org/pkg/sort/ // By is the type of a "less" function that defines the
class type User { name string } 是否可以在运行时添加字段age? 最佳答案 不,这是不可能的。 即使使用 Java 或 C++ 语法代替有效的 Go 也不行。
当我编译下面的程序时 func myPrint(v ...interface{}) { fmt.Println("Hello", v...) } func main() { m
有一个问题,这里发生了什么? forever := make(chan bool) log.Printf(" [*] Waiting for messages. To exit press CTRL+
当我运行我的 GoLang 程序时,它抛出了这个异常: packages/go-lang/1.3/pkg/tool/linux_amd64/6l: readsym 不同步 它是否来 self 的 am
我时常会遇到诸如零垃圾或有效使用内存等概念。例如在知名包的特性部分 httprouter您可以看到以下内容: Zero Garbage: The matching and dispatching pr
最近读了golang规范,遇到了一些有趣的操作符: & bitwise AND integers | bitwise OR integers
有这个包https://github.com/open-telemetry/opentelemetry-proto其中仅包含 protobuf 定义。要生成 golang 代码,必须输入: make
有这个包https://github.com/open-telemetry/opentelemetry-proto其中仅包含 protobuf 定义。要生成 golang 代码,必须输入: make
我正在使用下面的代码连接到 grpc 服务器,clientConn 对象用于所有后续的 rpc 调用。 maxDelay 设置为 5 秒。现在由于服务器出现问题,它没有响应 grpc 调用。所以我的客
初始数据: rawdata := []int{17, 23, 100500} 结果: result := convert(rawdata) expected := "1723100500" 我应该用
我想用我的智能手机操作我的窗帘。现在每次我改变手机的位置时都有一个方法 func main() { OnUpdate(func(tPos int) { wc(tPos,cPos)
我是一名优秀的程序员,十分优秀!