douhuang4166 2018-11-22 10:56
浏览 83
已采纳

如何在切片上查找而从切片复制到阵列

I'm writing a library to deal with a binary format.

I have a struct with array vars, that I would like to keep for documentation purposes.

I need also to seek and tell from the input slice of bytes.

Some pseudocode:

type foo struct {
    boo [5]byte
    coo [3]byte
}

func main() {

    // input is a []byte full of datas, read from a file

    var bar foo

    // Here i need something that writes 5 bytes to bar.foo from input
    bar.foo = somefunc(input, numberOfFoo) // ???
    // I need also tell() and seek()
    input.seek(n)

}

How can I do that with a single function?

  • 写回答

1条回答 默认 最新

  • doumeng9188 2018-11-22 11:23
    关注

    Operating on byte slice input

    You may use the builtin copy() to copy bytes from a source slice into a destination. If you have an array, slice it to obtain a slice, e.g. bar.boo[:]. To seek, just use a different offset in the source slice, also by reslicing it, e.g. input[startPos:].

    For example:

    input := []byte{1, 2, 3, 4, 5, 0, 0, 8, 9, 10}
    
    var bar foo
    copy(bar.boo[:], input)
    
    // Skip 2 bytes, seek to the 8th byte:
    input = input[7:]
    
    copy(bar.coo[:], input)
    
    fmt.Printf("%+v", bar)
    

    Output (try it on the Go Playground):

    {boo:[1 2 3 4 5] coo:[8 9 10]}
    

    Creating a ReadSeeker

    Another option is to wrap your input byte slice into an io.ReadSeeker such as bytes.Reader, then you can read from it.

    For example:

    input := []byte{1, 2, 3, 4, 5, 0, 0, 8, 9, 10}
    r := bytes.NewReader(input)
    
    var bar foo
    if _, err := io.ReadFull(r, bar.boo[:]); err != nil {
        panic(err)
    }
    
    // Skip 2 bytes, seek to the 8th byte:
    if _, err := r.Seek(7, io.SeekStart); err != nil {
        panic(err)
    }
    
    if _, err := io.ReadFull(r, bar.coo[:]); err != nil {
        panic(err)
    }
    
    fmt.Printf("%+v", bar)
    

    Output is the same, try it on the Go Playground.

    Using encoding/binary

    Yet another solution would be to use encoding/binary to read your whole struct in one step.

    In order to do this, we need to export the fields, and we have to insert an anonymous or blank field that covers the skipped bytes:

    type foo struct {
        Boo [5]byte
        _   [2]byte // don't care
        Coo [3]byte
    }
    

    Having the above type, we can read all of it in one step like this:

    input := []byte{1, 2, 3, 4, 5, 0, 0, 8, 9, 10}
    r := bytes.NewReader(input)
    
    var bar foo
    if err := binary.Read(r, binary.LittleEndian, &bar); err != nil {
        panic(err)
    }
    
    fmt.Printf("%+v", bar)
    

    Output is similar, except that it also displays the anonymous field (try it on the Go Playground):

    {Boo:[1 2 3 4 5] _:[0 0] Coo:[8 9 10]}
    

    See related answer: Why use arrays instead of slices?

    Reading directly from the original file

    You mentioned your input slice is from reading a file. Note that you do not need to read the file prior, as os.File implements io.Reader, even io.ReadSeeker, which means you can read from it directly, see the Creating a ReadSeeker section. You can also directly apply the encoding/binary solution, as we used a reader in that solution too.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料