4


I'm trying to reimplement a program it did in C a few years ago in Go
The program should read a "record"-like structured binary file and do something with the record (what is done with the records itself is not relevant for this question)

Such a datafile consists of many records where each record has the following definition:

REC_LEN   U2 // length of record after header
REC_TYPE  U1 //a type
REC_SUB   U1 //a subtype
REC_LEN x U1 //"payload" 

My problem now is how to specify that variable length byte[] in a struct in Go?
My plan was to use binary.Read to read the records
Here's what I've tried so far in Go:

type Record struct {
    rec_len uint16
    rec_type uint8
    rec_sub uint8
    data [rec_len]byte
}

Unfortunatelly it seems I can't reference a field of a struct within the same struct as I get the following error:

xxxx.go:15: undefined: rec_len
xxxx.go:15: invalid array bound rec_len

I'd appreciate any ideas pointing me in the right direction
Thanks
KR

3
  • This needs dependent typing, which Go doesn't support. You should instead read the fields separately and construct the value of the struct type manually, rather than attempting to read into the struct directly. Commented Jan 18, 2015 at 18:01
  • Can someone please explain the downvote? Would be good to know what's wrong to avoid that in the future Commented Jan 19, 2015 at 18:35
  • @FloF, perhaps it was "This question does not show any research effort;" I would hope that it is expected that questioners have read the basic documentation/spec/resources. If you had, you'd know Go has slices and arrays and why [rec_len]byte makes no sense without having to ask others to interpret the spec for you. Commented Apr 11, 2015 at 23:30

1 Answer 1

3

You can read the record as follows:

var rec Record

// Slurp up the fixed sized header.

var buf [4]byte
_, err := io.ReadFull(r, buf[:])
if err != nil {
    // handle error
}
rec.rec_len = binary.BigEndian.Uint16(buf[0:2])
rec.rec_type = buf[2]
rec.rec_sub = buf[3]

// Create the variable part and read it.

rec.data = make([]byte, rec.rec_len)
_, err = io.ReadFull(r, rec.data)
if err != nil {
    // handle error
}
Sign up to request clarification or add additional context in comments.

1 Comment

That's basically the way I've solved it. I was just hoping for a more "elegant" way ;)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.