gpt4 book ai didi

sql - 使用 SQL 和 gRPC 时如何使用 Scan 和 Value?

转载 作者:行者123 更新时间:2023-12-01 20:27:28 24 4
gpt4 key购买 nike

谁能解释一下如何正确使用Scan()Value()在下面的例子中?

我正在尝试使用以下示例:

  • https://github.com/jinzhu/gorm/issues/2017#issuecomment-537627961
  • https://github.com/travisjeffery/proto-go-sql/blob/master/_example/person_sql.go

  • 我的原型(prototype):
    message Timestamp {
    google.protobuf.Timestamp timestamp = 1;
    }
    message User {
    uint32 ID = 1;
    Timestamp createdAt = 2;
    }

    代码(需要修复 time.Now() ):
    package v1

    import (
    "database/sql/driver"
    "fmt"
    "time"

    "github.com/golang/protobuf/ptypes"
    )

    func (u *User) Create() {
    u.CreatedAt = time.Now() // FIXME: ERROR. How do I make use of Scan() and Value() here?

    // saving to SQL database
    }

    func (ts *Timestamp) Scan(value interface{}) error {
    switch t := value.(type) {
    case time.Time:
    var err error
    ts.Timestamp, err = ptypes.TimestampProto(t)
    if err != nil {
    return err
    }
    default:
    return fmt.Errorf("Not a protobuf Timestamp")
    }
    return nil
    }

    func (ts Timestamp) Value() (driver.Value, error) {
    return ptypes.Timestamp(ts.Timestamp)
    }

    最佳答案

    扫描器和评估器接口(interface)并不是您自己会真正使用的东西,至少在将自定义类型存储在数据库中时不会。我将首先介绍 Scan() 的使用。和 Value()功能,然后我会解决你的问题。

    当您收到 sql.Row结果,并希望将结果集中的值分配(扫描)到自定义类型的变量中。文档显示 sql.Row.Scan()函数接受 0 个或多个 interface{} 类型的参数,基本上什么都有。 (check docs here)。

    在可以扫描值的支持类型列表中,最后一行是重要的:

    any type implementing Scanner (see Scanner docs)



    使用功能 func (ts *Timestamp) Scan(value interface{}) error { , Timestamp类型现在实现 Scanner接口(interface),从而允许 sql.Row为这种类型赋值。 Scanner 的文档界面位于 Scan() 文档的正下方,我在上面链接。

    当然,这有助于您从数据库中读取值,但在存储这些类型时却一无所获。为此,您需要 Valuer界面。如果您还没有猜到, func (ts Timestamp) Value() (driver.Value, error)功能确实使您的 Timestamp type 实现了这个接口(interface)。 driver.Valuer 的文档接口(interface)可以找到 here ,一直在底部。
    Valuer的要点|接口(interface)是允许将任何类型转换为 driver.Value 的方法。 ,驱动程序可以使用并存储在数据库中(再次: docs here)。

    修复问题

    首先,我必须假设您的协议(protocol)输出已写入 v1包裹。如果不是,它对你来说不会很好。

    违规行确实是您标记的行:
    u.CreatedAt = time.Now()

    首先, User.CreatedAtTimestamp 类型,它本身就是一条包含单个时间戳的消息。设置 CreatedAt时间到 time.Now() , 你需要初始化 CreatedAt正确字段:
    u.CreatedAt = &Timestamp{
    Timestamp: ptypes.TimestampNow(), // this returns a PROTOBUF TYPE!
    }

    您在 Scan 中执行此操作和 Value功能已经,所以我真的不明白你为什么不在这里做......

    建议

    如果 protoc 输出确实写入了 v1包,我真的,真的会删除 User.Create()功能。事实上,我会直接杀死它。您的 Protocol Buffer 用于通信。通过 RPC 公开您的程序。这是一个 API。这些 message类型本质上是请求和响应对象(如果您愿意,可以称其为 DTO)。您正在添加此 Create对它起作用,从而将它们转换为 AR 类型。它使您的 protobuf 包无法使用。 gRPC 的美妙之处在于您可以生成 golang、C++、Python 等其他人可以用来调用您的程序的代码。如果你让你的 gRPC 包依赖于数据库,就像你正在做的那样,我个人永远不会使用它。

    关于sql - 使用 SQL 和 gRPC 时如何使用 Scan 和 Value?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59079565/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com