创建包含指针的 Go 结构的可重复字节数组
Create repeatable byte array of Go struct which contains a pointer
我希望能够在 Go 中创建结构的可重复字节数组,这样我就可以对它们进行哈希处理,然后在某个时候验证该哈希值。
我目前正在按照这种简单的方法从结构创建字节数组:
[]byte(fmt.Sprintf("%v", struct))...)
在我的结构包含一个带指针的嵌入式结构之前,这可以完美运行,例如:
type testEmbeddedPointerStruct struct {
T *testSimpleStruct
}
在我的测试中,这每次都会创建一个不同的字节数组,我认为这可能是因为每次使用指针时内存中的地址都会发生变化?
有没有一种方法可以创建可重复的字节数组摘要,即使该结构包含指针?
谢谢
... I think it may be because with the pointer the address in memory changes ...
这是显而易见的候选人,是的。您选择了一种非常简单的编码,其中指针字段被编码为指针的十六进制表示,而不是在指针目标处找到的任何值。
Is there a way of creating a repeatable byte array digest even if the struct holds a pointer?
您可能需要更准确地定义 "repeat of same value" 对您意味着什么,1 但总的来说,这确实是一个编码问题。 encoding/gob
包可能会为您提供您想要的编码,但请注意,与 %v
格式不同,它仅对导出的结构字段进行编码 并且 保留各种名称.它具有 "flattening" 任何指针数据的效果,但不适用于循环数据结构。
(您可以编写自己的更简单的编码器,它在遇到指针时简单地跟随指针,否则像 %v
一样工作。)
1例如,假设您有:
type T struct {
I int
P *Sub
}
type Sub struct {
J int
}
// ...
s2 := Sub{2}
s3 := Sub{3}
t1 := T{1, &s2}
t2 := T{1, &s3}
显然打印 t1 和 t2(同时压平指针)分别生成 {1 2}
和 {1 3}
的编码版本,因此它们不是相同的值。但是,如果我们将 s3
本身更改为:
s3 := Sub{2}
我们现在有两个不同的实体,t1
和 t2
,它们都是 "contain as a value" {1 2}
。在 Go 中,t1
和 t2
是不同的,因为它们的指针不同。换句话说,他们的价值观是不同的。在提议的encoding中,t1
和t2
都编码相同,所以它们是相同的值。
指针会出现这种情况:底层数据可能相同——某种意义上的 "same value"——但保存这些值的对象可能在位置上不同,因此如果一个对象是修改的,另一个不是。如果你 运行 这样的对象通过编码然后解码过程使它们 共享 指向 值,你可以给提高修改一个对象而不修改另一个对象或区分它们的能力。
既然你可以选择如何进行编码,你就可以准确地决定你想在这里发生什么。但你必须有意识地做出这样的选择,而不是偶然。
我希望能够在 Go 中创建结构的可重复字节数组,这样我就可以对它们进行哈希处理,然后在某个时候验证该哈希值。
我目前正在按照这种简单的方法从结构创建字节数组:
[]byte(fmt.Sprintf("%v", struct))...)
在我的结构包含一个带指针的嵌入式结构之前,这可以完美运行,例如:
type testEmbeddedPointerStruct struct {
T *testSimpleStruct
}
在我的测试中,这每次都会创建一个不同的字节数组,我认为这可能是因为每次使用指针时内存中的地址都会发生变化?
有没有一种方法可以创建可重复的字节数组摘要,即使该结构包含指针?
谢谢
... I think it may be because with the pointer the address in memory changes ...
这是显而易见的候选人,是的。您选择了一种非常简单的编码,其中指针字段被编码为指针的十六进制表示,而不是在指针目标处找到的任何值。
Is there a way of creating a repeatable byte array digest even if the struct holds a pointer?
您可能需要更准确地定义 "repeat of same value" 对您意味着什么,1 但总的来说,这确实是一个编码问题。 encoding/gob
包可能会为您提供您想要的编码,但请注意,与 %v
格式不同,它仅对导出的结构字段进行编码 并且 保留各种名称.它具有 "flattening" 任何指针数据的效果,但不适用于循环数据结构。
(您可以编写自己的更简单的编码器,它在遇到指针时简单地跟随指针,否则像 %v
一样工作。)
1例如,假设您有:
type T struct {
I int
P *Sub
}
type Sub struct {
J int
}
// ...
s2 := Sub{2}
s3 := Sub{3}
t1 := T{1, &s2}
t2 := T{1, &s3}
显然打印 t1 和 t2(同时压平指针)分别生成 {1 2}
和 {1 3}
的编码版本,因此它们不是相同的值。但是,如果我们将 s3
本身更改为:
s3 := Sub{2}
我们现在有两个不同的实体,t1
和 t2
,它们都是 "contain as a value" {1 2}
。在 Go 中,t1
和 t2
是不同的,因为它们的指针不同。换句话说,他们的价值观是不同的。在提议的encoding中,t1
和t2
都编码相同,所以它们是相同的值。
指针会出现这种情况:底层数据可能相同——某种意义上的 "same value"——但保存这些值的对象可能在位置上不同,因此如果一个对象是修改的,另一个不是。如果你 运行 这样的对象通过编码然后解码过程使它们 共享 指向 值,你可以给提高修改一个对象而不修改另一个对象或区分它们的能力。
既然你可以选择如何进行编码,你就可以准确地决定你想在这里发生什么。但你必须有意识地做出这样的选择,而不是偶然。