接受通用结构的函数

问题描述 投票:0回答:2

是否可以让我的函数定义接受任何类型的结构?

我试过像这样重构:

// This method should accept any type of struct
// Once I receive my response from the database,
// I scan the rows to create a slice of type struct.

func generateResponse(rows *sqlx.Rows, structSlice []struct{}, structBody struct{}) ([]struct{}, error) {
    for rows.Next() {

        err := rows.StructScan(&structBody)

        if err != nil {
            return nil, err
        }

        structSlice = append(structSlice, structBody)

    }

    err := rows.Err()
    if err != nil {
        return nil, err
    }

    return structSlice, nil
}

假设我的结构是

OrderRevenue
.

当我调用上面的函数时:

structSlice, err := generateResponse(rows, []OrderRevenue{}, OrderRevenue{})

我得到的错误是:

cannot use []OrderRevenue literal as type []struct{} in argument...

我是不是走错路了?

go refactoring
2个回答
2
投票

这被认为是 Go 类型系统的基石(或更多的限制)。

struct{}
是一个未命名的类型,它不同于
struct{ field1 int }
,当然也不等同于
OrderRevenue{}
.

Go 强调通过接口进行抽象,也许你应该尝试一下。这是第一次拍摄:

  type OrderRevenue interface {
          MarshalMyself() ([]byte, error)
  }

  type Anonymous struct {}
  func (a Anonymous) MarshalMyself() ([]byte, error) {
          // implementation's up to you
          return []byte{}, nil
  }

  // the function signature
  generateResponse(rows *sqlx.Rows, structSlice []OrderRevenue, structBody Body) ([]Body, error) {
          // ...
  }

在这种情况下,您还可以使用所有类型都实现的空接口

interface{}
,但您必须递归地遍历结构以进行手动类型断言。 Go 中最好的方法是提前知道数据的形状,至少是部分知道。


0
投票

也许你可以使用反射来检查你的参数是否是一个结构。

///some codes   
v := reflect.TypeOf(structBody)
if v.Kind() != reflect.Struct {
    return nil, fmt.Errorf("argument is not a struct")
}
///some codes

并且您使用泛型来指定参数的类型

func generateResponse[t any](rows *sqlx.Rows, structSlice []t, structBody t) ([]t, error) {

 v := reflect.TypeOf(structBody)
 if v.Kind() != reflect.Struct {
    return nil, fmt.Errorf("argument is not a struct")
 }

for rows.Next() {
   
    err := rows.StructScan(&structBody)

    if err != nil {
        return nil, err
    }

    structSlice = append(structSlice, structBody)

}

err := rows.Err()
if err != nil {
    return nil, err
}

return structSlice, nil

}

© www.soinside.com 2019 - 2024. All rights reserved.