gocb get原始二进制数据

2017-10-01  本文已影响0人  NeverLee

线上使用的couchbase被他们长期使用不标准的数据写入,导致gocb的get无法正常的解析数据,只能获取其原始二进制数据自己解析了。gocb文档和源码里都没有找到get原始二进制数据的办法。于是只好去抄gocb里的源码来改了。

方法一重新实现get

package main

import (
    "fmt"
    "gopkg.in/couchbase/gocb.v1"
    "gopkg.in/couchbase/gocbcore.v2"
    "time"
)

func GetRaw(agent *gocbcore.Agent, key string) (byteOut []byte, casOut gocbcore.Cas, errOut error) {
    signal := make(chan bool, 1)
    op, err := agent.Get([]byte(key), func(bytes []byte, flags uint32, cas gocbcore.Cas, err error) {
        if errOut == nil {
            casOut = cas
            byteOut = bytes
        }
        signal <- true
    })
    if err != nil {
        return nil, 0, err
    }

    opTimeout := 2500 * time.Millisecond
    timeoutTmr := gocbcore.AcquireTimer(opTimeout)
    select {
    case <-signal:
        gocbcore.ReleaseTimer(timeoutTmr, false)
        return
    case <-timeoutTmr.C:
        gocbcore.ReleaseTimer(timeoutTmr, true)
        if !op.Cancel() {
            <-signal
            return
        }
        return nil, 0, fmt.Errorf("Timeout")
    }
}

func main() {
    // For example
    myCluster, _ := gocb.Connect("couchbase://127.0.0.1")
    myBucket, _ := myCluster.OpenBucket("default", "")
    agent := myBucket.IoRouter()
    by, a, e := GetRaw(agent, "a_key")
    fmt.Println(k, len(by), a, e)
    agent.Close()
}

方法二实在一个新的transcoder

package main

import (
    "fmt"
    "gopkg.in/couchbase/gocb.v1"
    "gopkg.in/couchbase/gocbcore.v2"
)

type BytesTranscoder struct{}

// Decode applies the default Couchbase transcoding behaviour to decode into a Go byte slice.
func (t BytesTranscoder) Decode(bytes []byte, flags uint32, out interface{}) error {
    switch typedOut := out.(type) {
    case *[]byte:
        *typedOut = bytes
        return nil
    case *interface{}:
        *typedOut = bytes
        return nil
    case *string:
        *typedOut = string(bytes)
        return nil
    }
    return fmt.Errorf("Only support raw")
}

// Encode applies the default Couchbase transcoding behaviour to encode a Go byte slice.
func (t BytesTranscoder) Encode(value interface{}) ([]byte, uint32, error) {
    var bytes []byte
    cfFmtBinary := uint32(3 << 24)
    switch value.(type) {
    case []byte:
        bytes = value.([]byte)
    case *[]byte:
        bytes = *value.(*[]byte)
    case string:
        bytes = []byte(value.(string))
    case *string:
        bytes = []byte(*value.(*string))
    default:
        return nil, 0, fmt.Errorf("Unsupport type")
    }
    return bytes, cfFmtBinary, nil
}

func main() {
    myCluster, _ := gocb.Connect("couchbase://127.0.0.1")
    myBucket, _ := myCluster.OpenBucket("default", "")
    var bt BytesTranscoder
    myBucket.SetTranscoder(bt)

    var b []byte
    _, _ = myBucket.Get("a_key", &b)
    fmt.Println(string(b))
}

作者原创,转载请注明出处

上一篇下一篇

猜你喜欢

热点阅读