Note that there are some explanatory texts on larger screens.

plurals
  1. POUsing reflection with structs to build generic handler function
    primarykey
    data
    text
    <p>I have some trouble building a function that can dynamically use parametrized structs. For that reason my code has 20+ functions that are similar except basically for one type that gets used. Most of my experience is with Java, and I'd just develop basic generic functions, or use plain Object as parameter to function (and reflection from that point on). I would need something similar, using Go.</p> <p>I have several types like:</p> <pre><code>// The List structs are mostly needed for json marshalling type OrangeList struct { Oranges []Orange } type BananaList struct { Bananas []Banana } type Orange struct { Orange_id string Field_1 int // The fields are different for different types, I am simplifying the code example } type Banana struct { Banana_id string Field_1 int // The fields are different for different types, I am simplifying the code example } </code></pre> <p>Then I have function, basically for each list type:</p> <pre><code>// In the end there are 20+ of these, the only difference is basically in two types! // This is very un-DRY! func buildOranges(rows *sqlx.Rows) ([]byte, error) { oranges := OrangeList{} // This type changes for rows.Next() { orange := Orange{} // This type changes err := rows.StructScan(&amp;orange) // This can handle each case already, could also use reflect myself too checkError(err, "rows.Scan") oranges.Oranges = append(oranges.Oranges,orange) } checkError(rows.Err(), "rows.Err") jsontext, err := json.Marshal(oranges) return jsontext, err } </code></pre> <p>Yes, I could change the sql library to use more intelligent ORM or framework, but that's besides the point. I want to learn on how to build generic function that can handle similar function for all my different types. </p> <p>I got this far, but it still doesn't work properly (target isn't expected struct I think):</p> <pre><code>func buildWhatever(rows *sqlx.Rows, tgt interface{}) ([]byte, error) { tgtValueOf := reflect.ValueOf(tgt) tgtType := tgtValueOf.Type() targets := reflect.SliceOf(tgtValueOf.Type()) for rows.Next() { target := reflect.New(tgtType) err := rows.StructScan(&amp;target) // At this stage target still isn't 1:1 smilar struct so the StructScan fails... It's some perverted "Value" object instead. Meh. // Removed appending to the list because the solutions for that would be similar checkError(err, "rows.Scan") } checkError(rows.Err(), "rows.Err") jsontext, err := json.Marshal(targets) return jsontext, err } </code></pre> <p>So umm, I would need to give the list type, and the vanilla type as parameters, then build one of each, and the rest of my logic would be probably fixable quite easily.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload