douxigai8757 2018-03-13 19:36
浏览 56
已采纳

golang反映到[] interface {}

i wanna create a mini framework which takes a simple struct and creates a full crud out of it. i already started and the "findOne, update,create,delete" is working. not i have a problem to create a findAll method. to be more clear, i dont know how to use reflect to address my ptr to an array of struct.

Here a small example for the findOne function.

type company struct {
Id          int
Name        string
}

comp.InitModel(newDbConnection(), &comp)

In InitModel i can fill the pointer to the company with the following:

//m.caller = pointer to the ptr to comp (struct)
callerV := reflect.ValueOf(m.caller)
CallerField := callerV.Elem()
var values []interface{}
for _, e := range m.columns {
    values = append(values, CallerField.FieldByName(e.name).Addr().Interface())
}
err := r.Scan(values...)
if err != nil {
    return err
}

Now i wanna create a findAll method which would be called like this

var companies []company
comp.InitModel(newDbConnection(), &comp)
comp.FindAll(&companies) //in this is the db query and scan
fmt.Println(companies) //here should be the result

But i have a problem to get the reflect with a []interface working.

func (m *Model) FindAll(test []interface{}, c *Condition) error {

//get the sql statement from the struct
stmt := PrepairStmt(m, c)

rows, err := m.db.Query(stmt.selectParse(), c.arguments...)
if err != nil {
    return err
}
defer rows.Close()

callerV := reflect.ValueOf(m.caller)
CallerField := callerV.Elem()
for rows.Next() {

    var values []interface{}
    for _, e := range m.columns {
        values = append(values, CallerField.FieldByName(e.name).Addr().Interface())
    }

    err = rows.Scan(values...)
    if err != nil {
        return err
    }

    valuePtr := reflect.New(reflect.TypeOf(test).Elem())
    test = reflect.Append(test,reflect.ValueOf(values))
}

return nil
}

Thats were my latest tries. maybe someone can help me with this. i would be really thankful

  • 写回答

1条回答 默认 最新

  • douyou8047 2018-03-14 05:55
    关注

    Use interface{} instead of []interface{} as the argument type:

    func (m *Model) FindAll(result interface{}, c *Condition) error {
      stmt := PrepairStmt(m, c)
      rows, err := m.db.Query(stmt.selectParse(), c.arguments...)
      if err != nil {
        return err
      }
      defer rows.Close()
    
      // resultv is the result slice
      resultv := reflect.ValueOf(result).Elem()
    
      // rowt is the struct type
      rowt := resultv.Type().Elem()
    
      // allocate a value for the row
      rowv := reflect.New(rowt).Elem()
    
      // collect values for scan
      var values []interface{}
      for _, e := range m.columns {
          values = append(values, rowv.FieldByName(e.name).Addr().Interface())
      }
    
      for rows.Next() {
    
        err = rows.Scan(values...)
        if err != nil {
          return err
        }
    
        // Append struct to result slice. Because the struct
        // is copied in append, we can reuse the struct in 
        // this loop. 
        resultv.Set(reflect.Append(resultv, rowv))
      }
      return nil
    }
    

    Use it like this:

    var companies []company
    comp.InitModel(newDbConnection(), &comp)
    comp.FindAll(&companies) //in this is the db query and scan
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 双层网络上信息-疾病传播
  • ¥50 paddlepaddle pinn
  • ¥20 idea运行测试代码报错问题
  • ¥15 网络监控:网络故障告警通知
  • ¥15 django项目运行报编码错误
  • ¥15 请问这个是什么意思?
  • ¥15 STM32驱动继电器
  • ¥15 Windows server update services
  • ¥15 关于#c语言#的问题:我现在在做一个墨水屏设计,2.9英寸的小屏怎么换4.2英寸大屏
  • ¥15 模糊pid与pid仿真结果几乎一样