简体   繁体   English

在结构域上实现Redigo Scanner界面

[英]Implementing Redigo Scanner interface on a struct's field

I have a struct that looks like this: 我有一个看起来像这样的结构:

type authEnum int

const (
    never authEnum = iota
    sometimes
    always
)

type Attrs struct {
    Secret         string   `redis:"secret"`
    RequireSecret  authEnum `redis:"requireSecret"`
    UserID         string   `redis:"userId"`
}

func (e *authEnum) RedisScan(src interface{}) error {
    // This never gets called!
    if e == nil {
        return fmt.Errorf("nil pointer")
    }
    switch src := src.(type) {
    case string:
        if src == "false" || src == "never" {
            *e = never
        } else if src == "sometimes" {
            *e = sometimes
        } else { // "always" or "true"
            *e = always
        }
    default:
        return fmt.Errorf("cannot convert authEnum from %T to %T", src, e)
    }
    return nil
}

func getAttributes(ctx *AppContext, hash string) (*Attrs, error) {
    rc := ctx.RedisPool.Get()
    values, err := redis.Values(rc.Do("HGETALL", "redishash"))
    rc.Close()
    if err != nil {
        return nil, err
    }
    attrs := Attrs{}
    redis.ScanStruct(values, &attrs)
    return &attrs, nil
}

How do I implement the Scanner interface on the RequireSecret attribute to parse an authEnum type out of "never" , "sometimes" or "always" redis hash values? 如何在RequireSecret属性上实现Scanner接口,以从"never""sometimes""always" redis哈希值中解析authEnum类型?

How do I calculate the value and assign it to the authEnum? 如何计算值并将其分配给authEnum? In my code example RedisScan never gets called. 在我的代码示例中,从未调用过RedisScan

You don't implement interfaces on fields, but rather on types. 您不在字段上实现接口,而是在类型上实现接口。

You can make your authEnum type satisfy the interface, simply by creating a method with the signature RedisScan(src interface{}) error on that type. 您可以通过创建一个authEnum类型带有签名RedisScan(src interface{}) error的方法,使authEnum类型满足该接口。

To assign to the receiver, you need to receive a pointer. 要分配给接收者,您需要接收一个指针。 Then you can assign to it as so: 然后,您可以按以下方式为其分配:

func (e *authEnum) RedisScan(src interface{}) error {
    var value authEnum
    // Logic here to convert src to value
    *e = value
}

Implement the method on a pointer receiver. 在指针接收器上实现该方法。 Redis bulk strings are represented as []byte, not string: Redis批量字符串表示为[] byte,而不是字符串:

func (e *authEnum) RedisScan(src interface{}) error {
    b, ok := src.([]byte)
    if !ok {
        return fmt.Errorf("cannot convert authEnum from %T to %T", src, b)
    }
    switch string(b) {
    case "false", "never":
        *e = never
    case "sometimes":
        *e = sometimes
    default:
        *e = always
    }
    return nil
}

Always check and handle errors. 始终检查并处理错误。 The error returned from ScanStruct reports the type problem. ScanStruct返回的错误报告类型问题。

There's no need to check for nil pointer to the struct member. 无需检查指向struct成员的nil指针。 If the argument to ScanStruct is nil, then Redigo will panic well before the RedisScan method is called. 如果ScanStruct的参数为nil,则Redigo将在调用RedisScan方法之前恐慌。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM