2

I am reading from an io.Reader into a Struct, field by field.

// structFields returns a sequence of reflect.Value
for field := range structFields {
    switch field.Kind() {
    case reflect.String:
        // Omitted
    case reflect.Uint8:
        value := make([]byte, 2)
        reader.Read(value)

        var num uint8
        err := binary.Read(bytes.NewBuffer(value[:]), binary.LittleEndian, &num)
        if err != nil { return err }
        field.SetUint(int64(num))
    // Case statements for each of the other uint and int types omitted
    }
}

Unfortunately the block for reflect.Uint8 needs to be repeated for each of the Uint and Int data types since I need to create the var num correctly in each case.

Is there a way I can simplify this switch statement?

1
  • Although this does not solve this exact problem, you could replace all this logic with a simple call to binary.Read() which reads in all the fields of a struct in one go. Commented Jul 22, 2014 at 22:22

1 Answer 1

2

Instead of using var num uint8 and field.SetUint(int64(num)) just pass a pointer to the struct field to binary.Read:

ptr := field.Addr().Interface()
err := binary.Read(bytes.NewBuffer(value[:]), binary.LittleEndian, ptr)

And make the case statement say:

case reflect.Uint8, reflect.Int, reflect.Uint, ...:

Then you need to deal with differently-sized numbers. Fortunately you can just pass your reader directly to binary.Read and it'll take care of it:

err := binary.Read(reader, binary.LittleEndian, ptr)

Finally, as FUZxxl says, you can just pass a pointer to the entire struct to binary.Read and it'll do all this for you.

Sign up to request clarification or add additional context in comments.

2 Comments

@FUZxxl's solution wouldn't work unless all fields are sized ints, floats or complexes, it wouldn't work with any kind of a slice or a string.
Speaking of string fields, any recommendations on how to read those? I am trying to use a tag on the struct field, but I can not get to tags from a reflect.Value

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.