卓越飞翔博客卓越飞翔博客

卓越飞翔 - 您值得收藏的技术分享站
技术文章34079本站已运行391

如何在golang中向非本地结构添加接口?

如何在golang中向非本地结构添加接口?

问题内容

我使用 https://github.com/lib/pq 从 postgres 获取数据。 为了提取数据,我使用第三方结构,其中包含 protobuf timestamp 字段 https://pkg.go.dev/google.golang.org/protobuf/types/known/timestamppb#timestamp 所以 所以问题是让工作从 time.time 扫描到 timestamppb.timestamp

type stuff struct { //this struct non-local, this is from third-party package
  date *timestamppb.timestamp
}

stuff = stuff{}

scanerr := rows.scan(&stuff.date)

我尝试扫描结构实现 sql.scanner 接口。那很简单。我只是像这样实现 scan 功能:

type test struct {
}


func (t test) scan(src any) error {
//convert value
}

但它不适用于timestamppb.timestamp,因为它是非本地类型。 然后我尝试定义本地类型并执行相同的操作

type timestamppb timestamppb.timestamp

func (t timestamppb) scan(src any) error {
//convert value
}

但是这个技巧并没有奏效。此外,我有警告“‘scan’通过值传递锁:类型‘timestamppb’包含‘protoimpl.messagestate’包含‘sync.mutex’,即‘sync.locker’” 如果我为 timestamppb 指定指针,这将不起作用

func (t *timestamppb) scan(src any) error {

所以我想知道,如何制作 sql.scanner 的 timestamppb.timestamp 实例。可能吗?

更新 1 我尝试过的小例子

type TimestampPb timestamppb.Timestamp

type test struct { //third-party struct, I can't modify it
    date *timestamppb.Timestamp
}

func (s *Storage) test() {
    rows, _ := s.db.Query("SELECT "test_date" FROM "test_table" LIMIT 1")

    defer func() {
        if rows != nil {
            _ = rows.Close()
        }
    }()

    for rows.Next() {
        //var value *TimestampPb //works
        //var value TimestampPb //works
        //var value *timestamppb.Timestamp //doesn't work
        //testStruct := test{} //doesn't work

        //err := rows.Scan(&value) //scan to variable
        //err := rows.Scan(&testStruct.date) //scan to field in the struct
        if err != nil {
            log.Fatalln(err)
        }
    }
}

func (tpb *TimestampPb) Scan(src any) error {
    return nil
}

我想知道我是否可以将 case 与 teststruct 一起使用?


正确答案


pq 库不支持 *timestamppb.timestamp 作为时间戳类型。 请参阅文档中支持的日期类型。

扫描时需要不同的类型。

我通常通过在函数中使用辅助类型来做到这一点。例如:

type row struct {
  Date *timestamppb.Timestamp
  // ... more fields here
}

func Query() ([]row, error) {
    rows, err := s.db.Query(...)
  if err != nil {
    return nil, err
  }
  defer rows.Close()

  var rows []row
  for rows.Next() {
    type aux struct {
      Date time.Time
      // ... more fields here
    }
    var value aux
    if err := rows.Scan(&value); err != nil {
      return nil, err
    }
    rows = append(rows, row{
      Date: timestamppb.New(value.Date),
      // ... more fields here
    }
  }
  return rows, nil
}
卓越飞翔博客
上一篇: 在 Go 中使用泛型类型结构实现接口方法
下一篇: 返回列表
留言与评论(共有 0 条评论)
   
验证码:
隐藏边栏