Skip to content

Instantly share code, notes, and snippets.

@robertgro
Last active February 16, 2021 14:29
Show Gist options
  • Save robertgro/6fd0f1c9e7c7345985b5bfe32fed2ec0 to your computer and use it in GitHub Desktop.
Save robertgro/6fd0f1c9e7c7345985b5bfe32fed2ec0 to your computer and use it in GitHub Desktop.

Revisions

  1. robertgro revised this gist Feb 16, 2021. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion main.go
    Original file line number Diff line number Diff line change
    @@ -47,7 +47,7 @@ func (dW *dbWorker) AddNavItem() {
    }

    func (dW *dbWorker) changeValue(rv reflect.Value, cols []interface{}) {
    // due to interface{} being a pointer to type of v, dereference properly
    // rows.Scan(): due to interface{} being a pointer to type of v, dereference properly
    for i, v := range cols {
    switch v.(type) {
    case int: // *int
  2. robertgro revised this gist Feb 16, 2021. 1 changed file with 7 additions and 6 deletions.
    13 changes: 7 additions & 6 deletions main.go
    Original file line number Diff line number Diff line change
    @@ -47,14 +47,15 @@ func (dW *dbWorker) AddNavItem() {
    }

    func (dW *dbWorker) changeValue(rv reflect.Value, cols []interface{}) {
    // due to interface{} being a pointer to type of v, dereference properly
    for i, v := range cols {
    switch v.(type) {
    case int:
    rv.Field(i).SetInt(int64(v.(int)))
    case string:
    rv.Field(i).SetString(v.(string))
    case bool:
    rv.Field(i).SetBool(v.(bool))
    case int: // *int
    rv.Field(i).SetInt(int64(v.(int))) // rv.Field(i).SetInt(int64(*(v.(*int))))
    case string: // *string
    rv.Field(i).SetString(v.(string)) // rv.Field(i).SetString(*(v.(*string)))
    case bool: // *bool
    rv.Field(i).SetBool(v.(bool)) // rv.Field(i).SetBool(*(v.(*bool)))
    default:
    fmt.Printf("Type assert not defined. Type is %T", v)
    }
  3. robertgro revised this gist Feb 16, 2021. 1 changed file with 3 additions and 4 deletions.
    7 changes: 3 additions & 4 deletions main.go
    Original file line number Diff line number Diff line change
    @@ -76,8 +76,7 @@ func (dW *dbWorker) rowsNextIteration(newint int, newstr string) {

    for i := 0; i < num; i++ {
    field := em.Field(i)
    cols[i] = field.Interface() // note: rows.Scan() expects a pointer so you'll need to use field.Addr().Interface()
    // credits https://stackoverflow.com/a/56929480/11141257
    cols[i] = field.Interface()

    /*
    switch cols[i].(type) {
    @@ -90,7 +89,7 @@ func (dW *dbWorker) rowsNextIteration(newint int, newstr string) {
    cols[i] = "str2"
    field.SetString(cols[i].(string))
    default:
    println("Type assert not defined. Type is ", field.Type().String())
    fmt.Printf("Type assert not defined. Type is %T", v)
    }
    */

    @@ -150,4 +149,4 @@ func ptr(v reflect.Value) reflect.Value {
    pv := reflect.New(pt.Elem()) // create a reflect.Value of type *T.
    pv.Elem().Set(v) // sets pv to point to underlying value of v.
    return pv
    }
    }
  4. robertgro revised this gist Feb 16, 2021. 1 changed file with 5 additions and 2 deletions.
    7 changes: 5 additions & 2 deletions main.go
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,9 @@
    package main

    import "reflect"
    import (
    "fmt"
    "reflect"
    )

    // to be used in association with the golang sql package, rows.Scan()
    // pass in any struct object/object slice you like and get appropriate results using reflection
    @@ -53,7 +56,7 @@ func (dW *dbWorker) changeValue(rv reflect.Value, cols []interface{}) {
    case bool:
    rv.Field(i).SetBool(v.(bool))
    default:
    println("Type assert not defined. Type is ", rv.Field(i).Type().String())
    fmt.Printf("Type assert not defined. Type is %T", v)
    }
    }
    }
  5. robertgro revised this gist Feb 16, 2021. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion main.go
    Original file line number Diff line number Diff line change
    @@ -73,7 +73,7 @@ func (dW *dbWorker) rowsNextIteration(newint int, newstr string) {

    for i := 0; i < num; i++ {
    field := em.Field(i)
    cols[i] = field.Interface() // note: rows.Scan() expects a pointer so you'll need use field.Addr().Interface()
    cols[i] = field.Interface() // note: rows.Scan() expects a pointer so you'll need to use field.Addr().Interface()
    // credits https://stackoverflow.com/a/56929480/11141257

    /*
  6. robertgro revised this gist Feb 16, 2021. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion main.go
    Original file line number Diff line number Diff line change
    @@ -73,7 +73,8 @@ func (dW *dbWorker) rowsNextIteration(newint int, newstr string) {

    for i := 0; i < num; i++ {
    field := em.Field(i)
    cols[i] = field.Interface()
    cols[i] = field.Interface() // note: rows.Scan() expects a pointer so you'll need use field.Addr().Interface()
    // credits https://stackoverflow.com/a/56929480/11141257

    /*
    switch cols[i].(type) {
  7. robertgro created this gist Feb 16, 2021.
    149 changes: 149 additions & 0 deletions main.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,149 @@
    package main

    import "reflect"

    // to be used in association with the golang sql package, rows.Scan()
    // pass in any struct object/object slice you like and get appropriate results using reflection
    // restriction: the sql query result's columns length must match the struct object fields length (len(rows.Columns(), fix your query)
    // feel free to use, share, modify, expand, w/e. no license agreement
    // annotations left, primarily for me to learn more about golang, reflection and data types as such
    // this example pulls 'sidebar' items into a slice for furhter usage (json marshalling)
    // doesn't claim to be idiomatic or best practice. use at your own risk!

    type (
    navItem struct {
    ID int
    Name string
    }
    navItemList struct {
    NvL []navItem
    }
    dbWorker struct {
    queryObj interface{}
    queryObjL interface{}
    }
    )

    func (dW *dbWorker) AddNavItem() {
    rSPtr := ptr(reflect.ValueOf(dW.queryObjL))
    rVPtr := ptr(reflect.ValueOf(dW.queryObj))

    /*
    println(rSPtr.String(), rSPtr.Elem().String(), rSPtr.Elem().Elem().String(), rSPtr.Elem().Elem().CanSet())
    <**main.navItemList Value> <*main.navItemList Value> <main.navItemList Value> true
    */

    ev := rSPtr.Elem().Elem().Field(0) // may be a subject to change due dynamic field allocation demand

    /*
    println(ev.String(), ev.Type().String(), ev.CanSet())
    <[]main.navItem Value> []main.navItem true
    */

    ev.Set(reflect.Append(ev, rVPtr.Elem().Elem()))
    }

    func (dW *dbWorker) changeValue(rv reflect.Value, cols []interface{}) {
    for i, v := range cols {
    switch v.(type) {
    case int:
    rv.Field(i).SetInt(int64(v.(int)))
    case string:
    rv.Field(i).SetString(v.(string))
    case bool:
    rv.Field(i).SetBool(v.(bool))
    default:
    println("Type assert not defined. Type is ", rv.Field(i).Type().String())
    }
    }
    }

    func (dW *dbWorker) rowsNextIteration(newint int, newstr string) {

    rv := ptr(reflect.ValueOf(dW.queryObj))

    /*
    println(rv.String(), rv.Elem().String(), rv.Elem().Elem().String(), rv.Elem().Elem().CanSet())
    <**main.navItem Value> <*main.navItem Value> <main.navItem Value> true
    */

    em := rv.Elem().Elem()
    num := em.NumField()
    cols := make([]interface{}, num)

    for i := 0; i < num; i++ {
    field := em.Field(i)
    cols[i] = field.Interface()

    /*
    switch cols[i].(type) {
    case int:
    println("ID-A", cols[i].(int))
    cols[i] = 3
    field.SetInt(int64(cols[i].(int)))
    case string:
    println("NAME-A", cols[i].(string))
    cols[i] = "str2"
    field.SetString(cols[i].(string))
    default:
    println("Type assert not defined. Type is ", field.Type().String())
    }
    */

    }

    /*
    println("ID-A", cols[0].(int))
    println("NAME-A", cols[1].(string))
    */

    cols[0] = newint
    cols[1] = newstr
    dW.changeValue(em, cols)
    dW.AddNavItem()
    }

    func main() {

    ni := &navItem{}
    ni.ID = 2
    ni.Name = "str1"
    nis := &navItemList{}
    myWorker := &dbWorker{}
    println("NvL-A", len(nis.NvL))

    /*
    nis.NvL = append(nis.NvL, *ni)
    println("NvL-B", len(nis.NvL))
    */

    myWorker.queryObjL = nis
    myWorker.queryObj = ni
    myWorker.rowsNextIteration(3, "str2")
    myWorker.rowsNextIteration(4, "str3")
    myWorker.rowsNextIteration(5, "str4")

    /*
    myWorker.AddNavItem()
    println("ID-B", ni.ID)
    println("NAME-B", ni.Name)
    */

    println("NvL-B", len(nis.NvL))
    printSlice(*nis)
    }

    func printSlice(niL navItemList) {
    for k, v := range niL.NvL {
    println("NavItems", "key", k, "id", v.ID, "name", v.Name)
    }
    }

    // credits to https://github.com/a8m/reflect-examples
    // ptr wraps the given value with pointer: V => *V, *V => **V, etc.
    func ptr(v reflect.Value) reflect.Value {
    pt := reflect.PtrTo(v.Type()) // create a *T type.
    pv := reflect.New(pt.Elem()) // create a reflect.Value of type *T.
    pv.Elem().Set(v) // sets pv to point to underlying value of v.
    return pv
    }