如何在Go中比较指针?

pet*_*ica -8 comparison pointers go

我建立一些测试代码,我尝试用比较指针<>运营商。我的目标是将元素排序为平衡的树结构(由我实现)。为此,我需要快速,通用的比较。遵循良好的旧C / C ++习惯,我目前的想法是(...在撰写本文时是)通过指针地址对其进行比较。

但是,正如我发现的那样,它不起作用。来源

if (&(a.val) < &(b.val)) {
Run Code Online (Sandbox Code Playgroud)

给出编译错误

./pointer.go:40:无效的操作:&a.val <&b.val(运算符<未在指针上定义)

a并且b是带有valas(安全)指针成员的结构。

可以比较安全指针吗?怎么样?

是否保证指针的顺序保持不变?(例如,我可以想象一些GC技巧也会对数据重新排序。)

Ken*_*ant 5

是否保证指针的顺序保持不变?(例如,我可以想象一些GC技巧也会对数据重新排序。)

在回答问题的这一部分时,它看起来并不像它。请参阅下面的pkg不安全链接。

如果您想要一个指针的内存地址,请尝试使用不安全的程序包:

https://golang.org/pkg/unsafe/#Pointer

package main

import (
    "fmt"
    "unsafe"
)

func main() {
    var a,b int
    var pa,pb *int
    pa = &a
    pb = &b

    //var c int
    //pa = &c

    if uintptr(unsafe.Pointer(pa)) < uintptr(unsafe.Pointer(pb)) {
      fmt.Printf("a:%p > b:%p",pa,pb)   
    } else {
      fmt.Printf("b:%p > a:%p",pb,pa)
    }

}
Run Code Online (Sandbox Code Playgroud)

这将使您获得任意的Pointer类型,然后获得该指针的当前内存地址(如printf一样)。请注意此处的警告,您不能依赖此地址:

将Pointer转换为uintptr会生成所指向的值的内存地址(整数)。这种uintptr的通常用法是打印它。通常,将uintptr转换回Pointer无效。uintptr是整数,而不是引用。将Pointer转换为uintptr会创建一个没有指针语义的整数值。即使uintptr拥有某个对象的地址,垃圾回收器也不会在对象移动时更新该uintptr的值,也不会阻止uintptr回收该对象。

这会绕过Go类型的系统和内存安全性,因此这是不安全的,除非您只是进行实验,否则您可能不想这样做。我想不出在测试中这样做的理由,但是如果您想确保阅读整个文档并非常确定自己知道自己在做什么会按预期工作就可以了。

  • 我不建议不安全:)我认为有时值得解释为什么不安全以及如何做到这一点,以便人们可以做出明智的决定……也许还可以对go内存模型有所了解。 (3认同)