【问题标题】:golang reflect into []interface{}golang 反映到 []interface{}
【发布时间】:2018-08-22 04:51:25
【问题描述】:

我想创建一个迷你框架,它采用一个简单的结构并从中创建一个完整的 crud。我已经开始并且“findOne,更新,创建,删除”正在工作。不是我创建 findAll 方法有问题。更清楚地说,我不知道如何使用反射将我的 ptr 寻址到结构数组。

这里是 findOne 函数的一个小例子。

type company struct {
Id          int
Name        string
}

comp.InitModel(newDbConnection(), &comp)

在 InitModel 中,我可以用以下内容填充指向公司的指针:

//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
}

现在我想创建一个 findAll 方法,它会像这样调用

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

但是我在使用 [] 接口进行反射时遇到问题。

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
}

那是我最近的尝试。 也许有人可以帮助我。 我真的很感激

【问题讨论】:

  • test 是切片而不是reflect.Value,只需使用append
  • 嗯,但如果我想使用这样的功能,那就不行了。 Var 公司 []company comp.FindAll(&companies)
  • 那么companies 也是一个切片,但它是不同的类型,所以无论如何你都不能将它传递给 FindAll。

标签: go


【解决方案1】:

使用interface{} 而不是[]interface{} 作为参数类型:

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
}

像这样使用它:

var companies []company
comp.InitModel(newDbConnection(), &comp)
comp.FindAll(&companies) //in this is the db query and scan

【讨论】:

  • 太棒了,感谢您的示例和解释。现在我明白了!
猜你喜欢
  • 1970-01-01
  • 2018-08-06
  • 2015-05-02
  • 1970-01-01
  • 2016-03-21
  • 2021-06-22
  • 2015-03-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多