猿问

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

有人可以解释如何在下面的示例中正确使用Scan()and吗?Value()

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

我的原型:

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)

}


FFIVE
浏览 98回答 1
1回答

智慧大石

扫描器和评估器接口实际上并不是您自己使用的东西,至少在数据库中存储自定义类型时不是这样。Scan()我将首先介绍和函数的使用Value(),然后解决您的问题。当您获得sql.Row结果并想要将结果集中的值分配(扫描)到自定义类型的变量中时。文档显示该sql.Row.Scan()函数接受 0 个或多个类型的参数interface{},基本上是任何东西。在可以扫描值的支持类型列表中,最后一行是重要的一行:任何实现扫描仪的类型(请参阅扫描仪文档)通过 function func (ts *Timestamp) Scan(value interface{}) error {,该Timestamp类型现在实现了该Scanner接口,从而允许sql.Row向该类型分配值。该Scanner接口的文档位于Scan()我上面链接的 文档的正下方。当然,这可以帮助您从数据库读取值,但在存储这些类型时却无济于事。为此,您需要Valuer接口。如果您还没有猜到,该func (ts Timestamp) Value() (driver.Value, error)函数确实使您的Timestamp类型实现了此接口。该Valuer接口的要点是允许一种将任何类型转换为 a 的方法driver.Value,驱动程序可以使用该类型并将其存储在数据库中解决问题首先,我必须假设您的协议输出已写入包中v1。如果不是,它对你来说不会有很好的效果。有问题的行确实是您标记的行:u.CreatedAt = time.Now()首先,User.CreatedAt类型为Timestamp,它本身就是一条包含单个时间戳的消息。要将CreatedAt时间设置为time.Now(),您需要CreatedAt正确初始化该字段:u.CreatedAt = &Timestamp{     Timestamp: ptypes.TimestampNow(), // this returns a PROTOBUF TYPE!     }你已经Scan在你的函数中这样做了Value ,所以我真的不明白你为什么不在这里这样做......建议如果协议输出确实写入了v1包,我真的真的会删除该User.Create()函数。事实上,我会直接杀死它。您的协议缓冲区用于通信。通过 RPC 公开您的程序。这是一个 API。这些message类型本质上是请求和响应对象(如果您愿意的话,可以美化 DTO)。您正在Create向其中添加此功能,这会将它们变成 AR 类型。它使您的 protobuf 包无法使用。gRPC 的美妙之处在于您可以生成 golang、C++、Python...代码,其他人可以使用这些代码来调用您的程序。如果你让你的 gRPC 包依赖于数据库,就像你所做的那样,我个人永远不会使用它。
随时随地看视频慕课网APP

相关分类

Go
我要回答