How can I compare pointers in Go?

huangapple go评论84阅读模式
英文:

How can I compare pointers in Go?

问题

我正在构建一些测试代码,并尝试使用<>运算符来比较指针。我的目标是将元素排序到一个平衡的树结构中(由我实现)。为此,我需要快速、通用的比较方法。按照传统的C/C++习惯,我的当前想法(在撰写本帖时)是通过它们的指针地址进行比较。

然而,正如我所发现的那样,这并不起作用。下面的代码:

if (&(a.val) < &(b.val)) {

会导致编译错误:

./pointer.go:40: invalid operation: &a.val < &b.val (operator < not defined on pointer)

ab是具有val作为(安全的)指针成员的结构体。

在Go语言中,是否可以比较安全指针?如何比较?

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

英文:

I am building some test code and I try to compare pointers with the &lt;, &gt; operators. My goal is to order elements into a balanced tree structure (implemented by me). For that, I need quick, generic comparation. Following the good old C/C++ customs, my current idea is (...was, at the time of writing this post) to compare them by their pointer addresses.

However, as I've found, it doesn't work. The source

if (&amp;(a.val) &lt; &amp;(b.val)) {

gives the compile error

> ./pointer.go:40: invalid operation: &a.val < &b.val (operator < not defined on pointer)

a and b are structs with val as (safe) pointer member.

Is it possible to compare safe pointers in go? How?

Is it guaranteed that the order of the pointers remains the same? (For example, I can imagine some GC trickery which also reorders the data.)

答案1

得分: 7

“指针的顺序保持不变是有保证的吗?(例如,我可以想象一些垃圾回收的技巧也会重新排序数据。)”

对于你问题中的这部分回答来说,看起来并没有保证。请参考下面的链接中的 pkg unsafe。

如果你想要获取指针的内存地址,可以尝试使用 unsafe 包:

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)
	}

}

这样可以让你获取任意指针类型的当前内存地址(就像 printf 一样)。请注意其中的注意事项,你不能依赖这个地址:

“将指针转换为 uintptr 会产生指向值的内存地址,作为一个整数。通常使用 uintptr 的用途是打印它。将 uintptr 转换回 Pointer 通常是无效的。uintptr 是一个整数,而不是一个引用。将指针转换为 uintptr 会创建一个没有指针语义的整数值。即使 uintptr 持有某个对象的地址,如果该对象移动,垃圾回收器也不会更新该 uintptr 的值,也不会阻止该对象被回收。”

这会绕过 Go 类型系统和内存安全性,因此它是不安全的,你可能不想这样做,除非你只是在进行实验。我想不出在测试中这样做的理由,但如果你想确保读取整个文档并非常确定你知道你所做的事情将按照你的期望工作。

英文:

> Is it guaranteed that the order of the pointers remains the same? (For
> example, I can imagine some GC trickery which also reorders the data.)

In answer to this part of your question, it doesn't look like it. See pkg unsafe linked below.

If you want the memory address of a pointer, try the unsafe package:

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

package main

import (
	&quot;fmt&quot;
	&quot;unsafe&quot;
)

func main() {
	var a,b int
	var pa,pb *int
	pa = &amp;a
	pb = &amp;b
	
	//var c int
	//pa = &amp;c
	
	if uintptr(unsafe.Pointer(pa)) &lt; uintptr(unsafe.Pointer(pb)) {
	  fmt.Printf(&quot;a:%p &gt; b:%p&quot;,pa,pb)	
	} else {
	  fmt.Printf(&quot;b:%p &gt; a:%p&quot;,pb,pa)
	}

}

This will let you get an arbitrary Pointer type and then the current memory address of that pointer (as printf would). Note the caveats there though, you cannot rely on this address:

> Converting a Pointer to a uintptr produces the memory address of the
> value pointed at, as an integer. The usual use for such a uintptr is
> to print it. Conversion of a uintptr back to Pointer is not valid in
> general. A uintptr is an integer, not a reference. Converting a
> Pointer to a uintptr creates an integer value with no pointer
> semantics. Even if a uintptr holds the address of some object, the
> garbage collector will not update that uintptr's value if the object
> moves, nor will that uintptr keep the object from being reclaimed.

This bypasses the Go type system and memory security so it's unsafe and you probably don't want to do it, unless you're just experimenting. I can't think of a reason to do it in tests, but if you want to be sure to read that entire document and be very sure you know that what you are doing will work as you expect.

huangapple
  • 本文由 发表于 2017年8月22日 21:26:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/45818964.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定