我是Go的新手并试图编写一个读取RPM文件的应用程序.每个块的开头都有一个Magic char [4]byte.
这是我的结构
type Lead struct {
Magic [4]byte
Major, Minor byte
Type uint16
Arch uint16
Name string
OS uint16
SigType uint16
}
Run Code Online (Sandbox Code Playgroud)
我正在尝试执行以下操作:
lead := Lead{}
lead.Magic = buffer[0:4]
Run Code Online (Sandbox Code Playgroud)
我在网上搜索,不知道如何从切片到数组(不复制).我可以随时制作魔法[]byte(甚至是魔法uint64),但我更好奇的是[]byte,[4]byte如果需要,我将如何从类型转到?
twi*_*inj 35
内置方法副本仅将切片复制到切片而不是切片到数组.
你必须欺骗复制,认为数组是一个切片
copy(varLead.Magic[:], someSlice[0:4])
Run Code Online (Sandbox Code Playgroud)
或者使用for循环来执行复制:
for index, b := range someSlice {
varLead.Magic[index] = b
}
Run Code Online (Sandbox Code Playgroud)
或者像zupa使用文字一样.我已经添加了他们的工作示例.
去
1.181.191.20 将支持从切片到数组的转换:golang/goissues 46505。
因此,从 Go 1.18 开始,切片 copy2 实现可以写为:
*(*[N]T)(d) = [N]T(s)
Run Code Online (Sandbox Code Playgroud)
或者,如果允许转换以 L 值表示,则更简单:
[N]T(d) = [N]T(s)
Run Code Online (Sandbox Code Playgroud)
无需复制,您可以在下一个 Go 1.17(2021 年第 3 季度)中将切片转换为数组指针。
这称为“取消切片”,再次返回指向切片底层数组的指针,无需任何复制/分配:
请参阅golang/go问题 395:spec: convert slice x into array pointer,现在使用CL 216424/实现,并提交 1c26843
将切片转换为数组指针会生成指向切片底层数组的指针。
如果切片的长度小于数组的长度,则会发生运行时恐慌。
*(*[N]T)(d) = [N]T(s)
Run Code Online (Sandbox Code Playgroud)
所以在你的情况下,提供的Magic类型是*[4]byte:
lead.Magic = (*[4]byte)(buffer)
Run Code Online (Sandbox Code Playgroud)
注意:类型别名也可以工作:
[N]T(d) = [N]T(s)
Run Code Online (Sandbox Code Playgroud)
为什么要转换为数组指针?正如第 395 期所述:
这样做的动机之一是使用数组指针允许编译器在编译时对常量索引进行范围检查。
像这样的函数:
Run Code Online (Sandbox Code Playgroud)s := make([]byte, 2, 4) s0 := (*[0]byte)(s) // s0 != nil s2 := (*[2]byte)(s) // &s2[0] == &s[0] s4 := (*[4]byte)(s) // panics: len([4]byte) > len(s) var t []string t0 := (*[0]string)(t) // t0 == nil t1 := (*[1]string)(t) // panics: len([1]string) > len(s)可以变成:
Run Code Online (Sandbox Code Playgroud)lead.Magic = (*[4]byte)(buffer)允许编译器仅检查一次所有边界,并给出有关超出范围索引的编译时错误。
还:
一个常用的示例是使树节点或链表节点的类尽可能小,这样您就可以将尽可能多的类塞入 L1 缓存行中。
这是通过每个节点具有指向左子节点的单个指针,并且通过指向左子节点的指针+1来访问右子节点来完成的。
这为右节点指针节省了8个字节。为此,您必须预先分配向量或数组中的所有节点,以便它们按顺序布置在内存中,但当您需要它来提高性能时,这是值得的。
(这还有一个额外的好处,即预取器能够帮助提高性能 - 至少在链表情况下)你几乎可以在 Go 中做到这一点:
Run Code Online (Sandbox Code Playgroud)type A [4]int var s = (*A)([]int{1, 2, 3, 4})除了无法
*[2]node从底层切片中获取 a 之外。
Go 1.20(2023 年第一季度):通过CL 430415、428938 (type)、430475 (reflect)和429315 (spec)解决此问题。