Go 中有没有办法判断两个字符串是否共享内存?

问题描述 投票:0回答:2

在 Go 中,字符串在内部存储为 C 结构体:

struct String // This is C code (not Go)
{
  byte* str;
  int32 len;
};

假设我有以下变量:

a0 := "ap" // This is Go code
a1 := "ple"
b0 := "app"
b1 := "le"
a := a0 + a1
b := b0 + b1
c := "apple"
d := c

然后是以下代码:

fmt.Println("a == b = %t, &a == &b = %t", a == b, &a == &b)
fmt.Println("c == d = %t, &c == &d = %t", c == d, &c == &d)

输出:

a == b = true, &a == &b = false
c == d = true, &c == &d = false

因为

&a == &b
比较 C 结构体的地址,而
a == b
比较字符串的值。

有没有办法测试字符串本身是否存储在同一位置(即 C 结构中的

str
字段具有相同的值),这样比较
a
b
很可能会产生
 false
,而比较
c
d
几乎肯定会产生
true

string go equality
2个回答
5
投票

是的,这是可能的。使用reflect包并获取两个string实例的

String Headers
。然后,您可以比较 both
Data
Len
字段来计算字符串支持数组在内存中是否重叠。

注意:

StringHeader
结构是一个实现细节,语言规范中没有提及。因此,任何执行上一段讨论的代码都不是真正可移植的 Go。 IOW,我不鼓励在好奇心/研究等之外使用此类代码。来自文档:

StringHeader 是字符串的运行时表示。它不能安全或便携地使用,并且其表示形式可能会在以后的版本中发生变化。此外,Data 字段不足以保证它引用的数据不会被垃圾收集,因此程序必须保留一个单独的、类型正确的指向底层数据的指针。

编辑:

未经测试的从

*reflect.StringHeader
实例
hdr
获取
string
str
的代码:

hdr := (*reflect.StringHeader)(unsafe.Pointer(&str))

0
投票

从 Go 1.20 开始,你可以使用 unsafe.StringData

例如

unsafe.StringData(a) == unsafe.StringData(b) && len(a) == len(b)

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.