与私人界面

时间:2016-08-18 17:49:07

标签: go interface comparison

我有两个对象。 key1的类型为*rsa.PublicKeykey2的类型为*ssh.PublicKey,它是隐藏*ssh.rsaPublicKey对象的接口。 ssh.rsaPublicKey定义为:

type ssh.rsaPublicKey rsa.PublicKey

它有一些额外的方法。但是,我无法将关键字投放到ssh.rsaPublicKey,因为该类是"未导出",我无法将key2投射到rsa.PublicKey因为那并没有实现ssh.PublicKey,我无法从N访问ekey2,因为我不应该知道我有rsaPublicKey一个key1对象。

我应该如何比较key2eigen是否相同?

1 个答案:

答案 0 :(得分:2)

正如您所提到的,您无法使用type assertion,因为您无法引用未导出的类型ssh.rsaPublicKey

使用reflect包可以实现您的目标。

由于rsa.PublicKeyssh.rsaPublicKey的基础类型,key2中包含的指向值可以转换为rsa.PublicKey。获得key2的{​​{3}}后,使用reflect.Value“导航”到指向的值。此值可转换为类型rsa.PublicKey的值。您可以使用Value.Elem()“动态”,在运行时将其转换为rsa.PublicKey。获得后,您可以使用Value.Convert()进行比较,或手动比较。

这就是它的样子:

key1 := &rsa.PublicKey{N: big.NewInt(123), E: 10}
key2, _ := ssh.NewPublicKey(&rsa.PublicKey{N: big.NewInt(123), E: 10})


key2conv := reflect.ValueOf(key2).Elem().
    Convert(reflect.TypeOf(rsa.PublicKey{})).Interface()
// key2conf is an interface{}, wrapping an rsa.PublicKey

// Comparision with DeepEqual
fmt.Println(reflect.DeepEqual(*key1, key2conv))

// Comparing manually:
key22 := key2conv.(rsa.PublicKey)
fmt.Println(key1.N.Cmp(key22.N)) // Int.Cmp() returns 0 if equal
fmt.Println(key1.E == key22.E)

请注意,在手动比较时,比较PublicKey.N字段 - 类型为*big.Int - 您需要使用reflect.DeepEquals()方法,因为比较指针会比较内存地址,而不是指向内存地址值。如果2个值相等,则Int.Cmp()会返回0