mirror of https://github.com/go-redis/redis.git
Reduce number of allocations.
This commit is contained in:
parent
b9cc17bae0
commit
69554c0ec5
|
@ -37,7 +37,7 @@ func BenchmarkRedisPing(b *testing.B) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkRedisSet(b *testing.B) {
|
func BenchmarkRedisSetString(b *testing.B) {
|
||||||
client := benchmarkRedisClient(10)
|
client := benchmarkRedisClient(10)
|
||||||
defer client.Close()
|
defer client.Close()
|
||||||
|
|
||||||
|
|
|
@ -378,7 +378,7 @@ func (c *ClusterClient) cmdSlotAndNode(state *clusterState, cmd Cmder) (int, *cl
|
||||||
return 0, node, err
|
return 0, node, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdInfo := c.cmds[cmd.arg(0)]
|
cmdInfo := c.cmds[cmd.name()]
|
||||||
firstKey := cmd.arg(cmdFirstKeyPos(cmd, cmdInfo))
|
firstKey := cmd.arg(cmdFirstKeyPos(cmd, cmdInfo))
|
||||||
slot := hashtag.Slot(firstKey)
|
slot := hashtag.Slot(firstKey)
|
||||||
|
|
||||||
|
|
101
command.go
101
command.go
|
@ -33,6 +33,7 @@ var (
|
||||||
type Cmder interface {
|
type Cmder interface {
|
||||||
args() []interface{}
|
args() []interface{}
|
||||||
arg(int) string
|
arg(int) string
|
||||||
|
name() string
|
||||||
|
|
||||||
readReply(*pool.Conn) error
|
readReply(*pool.Conn) error
|
||||||
setErr(error)
|
setErr(error)
|
||||||
|
@ -83,7 +84,7 @@ func cmdString(cmd Cmder, val interface{}) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func cmdFirstKeyPos(cmd Cmder, info *CommandInfo) int {
|
func cmdFirstKeyPos(cmd Cmder, info *CommandInfo) int {
|
||||||
switch cmd.arg(0) {
|
switch cmd.name() {
|
||||||
case "eval", "evalsha":
|
case "eval", "evalsha":
|
||||||
if cmd.arg(2) != "0" {
|
if cmd.arg(2) != "0" {
|
||||||
return 3
|
return 3
|
||||||
|
@ -92,7 +93,7 @@ func cmdFirstKeyPos(cmd Cmder, info *CommandInfo) int {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if info == nil {
|
if info == nil {
|
||||||
internal.Logf("info for cmd=%s not found", cmd.arg(0))
|
internal.Logf("info for cmd=%s not found", cmd.name())
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
return int(info.FirstKeyPos)
|
return int(info.FirstKeyPos)
|
||||||
|
@ -126,6 +127,16 @@ func (cmd *baseCmd) arg(pos int) string {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cmd *baseCmd) name() string {
|
||||||
|
if len(cmd._args) > 0 {
|
||||||
|
// Cmd name must be lower cased.
|
||||||
|
s := internal.ToLower(cmd.arg(0))
|
||||||
|
cmd._args[0] = s
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func (cmd *baseCmd) readTimeout() *time.Duration {
|
func (cmd *baseCmd) readTimeout() *time.Duration {
|
||||||
return cmd._readTimeout
|
return cmd._readTimeout
|
||||||
}
|
}
|
||||||
|
@ -156,7 +167,7 @@ type Cmd struct {
|
||||||
|
|
||||||
func NewCmd(args ...interface{}) *Cmd {
|
func NewCmd(args ...interface{}) *Cmd {
|
||||||
return &Cmd{
|
return &Cmd{
|
||||||
baseCmd: newBaseCmd(args),
|
baseCmd: baseCmd{_args: args},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,8 +204,9 @@ type SliceCmd struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSliceCmd(args ...interface{}) *SliceCmd {
|
func NewSliceCmd(args ...interface{}) *SliceCmd {
|
||||||
cmd := newBaseCmd(args)
|
return &SliceCmd{
|
||||||
return &SliceCmd{baseCmd: cmd}
|
baseCmd: baseCmd{_args: args},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *SliceCmd) Val() []interface{} {
|
func (cmd *SliceCmd) Val() []interface{} {
|
||||||
|
@ -228,8 +240,9 @@ type StatusCmd struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewStatusCmd(args ...interface{}) *StatusCmd {
|
func NewStatusCmd(args ...interface{}) *StatusCmd {
|
||||||
cmd := newBaseCmd(args)
|
return &StatusCmd{
|
||||||
return &StatusCmd{baseCmd: cmd}
|
baseCmd: baseCmd{_args: args},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *StatusCmd) Val() string {
|
func (cmd *StatusCmd) Val() string {
|
||||||
|
@ -258,8 +271,9 @@ type IntCmd struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewIntCmd(args ...interface{}) *IntCmd {
|
func NewIntCmd(args ...interface{}) *IntCmd {
|
||||||
cmd := newBaseCmd(args)
|
return &IntCmd{
|
||||||
return &IntCmd{baseCmd: cmd}
|
baseCmd: baseCmd{_args: args},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *IntCmd) Val() int64 {
|
func (cmd *IntCmd) Val() int64 {
|
||||||
|
@ -289,10 +303,9 @@ type DurationCmd struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDurationCmd(precision time.Duration, args ...interface{}) *DurationCmd {
|
func NewDurationCmd(precision time.Duration, args ...interface{}) *DurationCmd {
|
||||||
cmd := newBaseCmd(args)
|
|
||||||
return &DurationCmd{
|
return &DurationCmd{
|
||||||
|
baseCmd: baseCmd{_args: args},
|
||||||
precision: precision,
|
precision: precision,
|
||||||
baseCmd: cmd,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,9 +340,8 @@ type TimeCmd struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTimeCmd(args ...interface{}) *TimeCmd {
|
func NewTimeCmd(args ...interface{}) *TimeCmd {
|
||||||
cmd := newBaseCmd(args)
|
|
||||||
return &TimeCmd{
|
return &TimeCmd{
|
||||||
baseCmd: cmd,
|
baseCmd: baseCmd{_args: args},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,8 +376,9 @@ type BoolCmd struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBoolCmd(args ...interface{}) *BoolCmd {
|
func NewBoolCmd(args ...interface{}) *BoolCmd {
|
||||||
cmd := newBaseCmd(args)
|
return &BoolCmd{
|
||||||
return &BoolCmd{baseCmd: cmd}
|
baseCmd: baseCmd{_args: args},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *BoolCmd) Val() bool {
|
func (cmd *BoolCmd) Val() bool {
|
||||||
|
@ -414,16 +427,17 @@ func (cmd *BoolCmd) readReply(cn *pool.Conn) error {
|
||||||
type StringCmd struct {
|
type StringCmd struct {
|
||||||
baseCmd
|
baseCmd
|
||||||
|
|
||||||
val string
|
val []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewStringCmd(args ...interface{}) *StringCmd {
|
func NewStringCmd(args ...interface{}) *StringCmd {
|
||||||
cmd := newBaseCmd(args)
|
return &StringCmd{
|
||||||
return &StringCmd{baseCmd: cmd}
|
baseCmd: baseCmd{_args: args},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *StringCmd) Val() string {
|
func (cmd *StringCmd) Val() string {
|
||||||
return cmd.val
|
return internal.BytesToString(cmd.val)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *StringCmd) Result() (string, error) {
|
func (cmd *StringCmd) Result() (string, error) {
|
||||||
|
@ -467,7 +481,7 @@ func (cmd *StringCmd) String() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *StringCmd) readReply(cn *pool.Conn) error {
|
func (cmd *StringCmd) readReply(cn *pool.Conn) error {
|
||||||
cmd.val, cmd.err = cn.Rd.ReadStringReply()
|
cmd.val, cmd.err = cn.Rd.ReadBytesReply()
|
||||||
return cmd.err
|
return cmd.err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -480,8 +494,9 @@ type FloatCmd struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFloatCmd(args ...interface{}) *FloatCmd {
|
func NewFloatCmd(args ...interface{}) *FloatCmd {
|
||||||
cmd := newBaseCmd(args)
|
return &FloatCmd{
|
||||||
return &FloatCmd{baseCmd: cmd}
|
baseCmd: baseCmd{_args: args},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *FloatCmd) Val() float64 {
|
func (cmd *FloatCmd) Val() float64 {
|
||||||
|
@ -510,8 +525,9 @@ type StringSliceCmd struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewStringSliceCmd(args ...interface{}) *StringSliceCmd {
|
func NewStringSliceCmd(args ...interface{}) *StringSliceCmd {
|
||||||
cmd := newBaseCmd(args)
|
return &StringSliceCmd{
|
||||||
return &StringSliceCmd{baseCmd: cmd}
|
baseCmd: baseCmd{_args: args},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *StringSliceCmd) Val() []string {
|
func (cmd *StringSliceCmd) Val() []string {
|
||||||
|
@ -545,8 +561,9 @@ type BoolSliceCmd struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBoolSliceCmd(args ...interface{}) *BoolSliceCmd {
|
func NewBoolSliceCmd(args ...interface{}) *BoolSliceCmd {
|
||||||
cmd := newBaseCmd(args)
|
return &BoolSliceCmd{
|
||||||
return &BoolSliceCmd{baseCmd: cmd}
|
baseCmd: baseCmd{_args: args},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *BoolSliceCmd) Val() []bool {
|
func (cmd *BoolSliceCmd) Val() []bool {
|
||||||
|
@ -580,8 +597,9 @@ type StringStringMapCmd struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewStringStringMapCmd(args ...interface{}) *StringStringMapCmd {
|
func NewStringStringMapCmd(args ...interface{}) *StringStringMapCmd {
|
||||||
cmd := newBaseCmd(args)
|
return &StringStringMapCmd{
|
||||||
return &StringStringMapCmd{baseCmd: cmd}
|
baseCmd: baseCmd{_args: args},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *StringStringMapCmd) Val() map[string]string {
|
func (cmd *StringStringMapCmd) Val() map[string]string {
|
||||||
|
@ -615,8 +633,9 @@ type StringIntMapCmd struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewStringIntMapCmd(args ...interface{}) *StringIntMapCmd {
|
func NewStringIntMapCmd(args ...interface{}) *StringIntMapCmd {
|
||||||
cmd := newBaseCmd(args)
|
return &StringIntMapCmd{
|
||||||
return &StringIntMapCmd{baseCmd: cmd}
|
baseCmd: baseCmd{_args: args},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *StringIntMapCmd) Val() map[string]int64 {
|
func (cmd *StringIntMapCmd) Val() map[string]int64 {
|
||||||
|
@ -650,8 +669,9 @@ type ZSliceCmd struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewZSliceCmd(args ...interface{}) *ZSliceCmd {
|
func NewZSliceCmd(args ...interface{}) *ZSliceCmd {
|
||||||
cmd := newBaseCmd(args)
|
return &ZSliceCmd{
|
||||||
return &ZSliceCmd{baseCmd: cmd}
|
baseCmd: baseCmd{_args: args},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *ZSliceCmd) Val() []Z {
|
func (cmd *ZSliceCmd) Val() []Z {
|
||||||
|
@ -689,7 +709,7 @@ type ScanCmd struct {
|
||||||
|
|
||||||
func NewScanCmd(process func(cmd Cmder) error, args ...interface{}) *ScanCmd {
|
func NewScanCmd(process func(cmd Cmder) error, args ...interface{}) *ScanCmd {
|
||||||
return &ScanCmd{
|
return &ScanCmd{
|
||||||
baseCmd: newBaseCmd(args),
|
baseCmd: baseCmd{_args: args},
|
||||||
process: process,
|
process: process,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -738,8 +758,9 @@ type ClusterSlotsCmd struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClusterSlotsCmd(args ...interface{}) *ClusterSlotsCmd {
|
func NewClusterSlotsCmd(args ...interface{}) *ClusterSlotsCmd {
|
||||||
cmd := newBaseCmd(args)
|
return &ClusterSlotsCmd{
|
||||||
return &ClusterSlotsCmd{baseCmd: cmd}
|
baseCmd: baseCmd{_args: args},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *ClusterSlotsCmd) Val() []ClusterSlot {
|
func (cmd *ClusterSlotsCmd) Val() []ClusterSlot {
|
||||||
|
@ -857,8 +878,9 @@ type GeoPosCmd struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGeoPosCmd(args ...interface{}) *GeoPosCmd {
|
func NewGeoPosCmd(args ...interface{}) *GeoPosCmd {
|
||||||
cmd := newBaseCmd(args)
|
return &GeoPosCmd{
|
||||||
return &GeoPosCmd{baseCmd: cmd}
|
baseCmd: baseCmd{_args: args},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *GeoPosCmd) Val() []*GeoPos {
|
func (cmd *GeoPosCmd) Val() []*GeoPos {
|
||||||
|
@ -902,8 +924,9 @@ type CommandsInfoCmd struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCommandsInfoCmd(args ...interface{}) *CommandsInfoCmd {
|
func NewCommandsInfoCmd(args ...interface{}) *CommandsInfoCmd {
|
||||||
cmd := newBaseCmd(args)
|
return &CommandsInfoCmd{
|
||||||
return &CommandsInfoCmd{baseCmd: cmd}
|
baseCmd: baseCmd{_args: args},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *CommandsInfoCmd) Val() map[string]*CommandInfo {
|
func (cmd *CommandsInfoCmd) Val() map[string]*CommandInfo {
|
||||||
|
|
|
@ -74,7 +74,7 @@ func (p *Reader) ReadReply(m MultiBulkParse) (interface{}, error) {
|
||||||
case StatusReply:
|
case StatusReply:
|
||||||
return parseStatusValue(line)
|
return parseStatusValue(line)
|
||||||
case IntReply:
|
case IntReply:
|
||||||
return parseIntValue(line)
|
return parseInt(line[1:], 10, 64)
|
||||||
case StringReply:
|
case StringReply:
|
||||||
return p.readBytesValue(line)
|
return p.readBytesValue(line)
|
||||||
case ArrayReply:
|
case ArrayReply:
|
||||||
|
@ -96,13 +96,13 @@ func (p *Reader) ReadIntReply() (int64, error) {
|
||||||
case ErrorReply:
|
case ErrorReply:
|
||||||
return 0, ParseErrorReply(line)
|
return 0, ParseErrorReply(line)
|
||||||
case IntReply:
|
case IntReply:
|
||||||
return parseIntValue(line)
|
return parseInt(line[1:], 10, 64)
|
||||||
default:
|
default:
|
||||||
return 0, fmt.Errorf("redis: can't parse int reply: %.100q", line)
|
return 0, fmt.Errorf("redis: can't parse int reply: %.100q", line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Reader) ReadBytesReply() ([]byte, error) {
|
func (p *Reader) ReadTmpBytesReply() ([]byte, error) {
|
||||||
line, err := p.ReadLine()
|
line, err := p.ReadLine()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -119,8 +119,18 @@ func (p *Reader) ReadBytesReply() ([]byte, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Reader) ReadBytesReply() ([]byte, error) {
|
||||||
|
b, err := r.ReadTmpBytesReply()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
cp := make([]byte, len(b))
|
||||||
|
copy(cp, b)
|
||||||
|
return cp, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Reader) ReadStringReply() (string, error) {
|
func (p *Reader) ReadStringReply() (string, error) {
|
||||||
b, err := p.ReadBytesReply()
|
b, err := p.ReadTmpBytesReply()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -128,11 +138,11 @@ func (p *Reader) ReadStringReply() (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Reader) ReadFloatReply() (float64, error) {
|
func (p *Reader) ReadFloatReply() (float64, error) {
|
||||||
s, err := p.ReadStringReply()
|
b, err := p.ReadTmpBytesReply()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
return strconv.ParseFloat(s, 64)
|
return parseFloat(b, 64)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Reader) ReadArrayReply(m MultiBulkParse) (interface{}, error) {
|
func (p *Reader) ReadArrayReply(m MultiBulkParse) (interface{}, error) {
|
||||||
|
@ -178,12 +188,7 @@ func (p *Reader) ReadScanReply() ([]string, uint64, error) {
|
||||||
return nil, 0, fmt.Errorf("redis: got %d elements in scan reply, expected 2", n)
|
return nil, 0, fmt.Errorf("redis: got %d elements in scan reply, expected 2", n)
|
||||||
}
|
}
|
||||||
|
|
||||||
s, err := p.ReadStringReply()
|
cursor, err := p.ReadUint()
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
cursor, err := strconv.ParseUint(s, 10, 64)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
@ -222,6 +227,22 @@ func (p *Reader) readBytesValue(line []byte) ([]byte, error) {
|
||||||
return b[:replyLen], nil
|
return b[:replyLen], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Reader) ReadInt() (int64, error) {
|
||||||
|
b, err := r.ReadTmpBytesReply()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return parseInt(b, 10, 64)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Reader) ReadUint() (uint64, error) {
|
||||||
|
b, err := r.ReadTmpBytesReply()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return parseUint(b, 10, 64)
|
||||||
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------
|
// --------------------------------------------------------------------
|
||||||
|
|
||||||
func readN(r io.Reader, b []byte, n int) ([]byte, error) {
|
func readN(r io.Reader, b []byte, n int) ([]byte, error) {
|
||||||
|
@ -280,13 +301,25 @@ func parseStatusValue(line []byte) ([]byte, error) {
|
||||||
return line[1:], nil
|
return line[1:], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseIntValue(line []byte) (int64, error) {
|
|
||||||
return strconv.ParseInt(string(line[1:]), 10, 64)
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseArrayLen(line []byte) (int64, error) {
|
func parseArrayLen(line []byte) (int64, error) {
|
||||||
if isNilReply(line) {
|
if isNilReply(line) {
|
||||||
return 0, internal.Nil
|
return 0, internal.Nil
|
||||||
}
|
}
|
||||||
return parseIntValue(line)
|
return parseInt(line[1:], 10, 64)
|
||||||
|
}
|
||||||
|
|
||||||
|
func atoi(b []byte) (int, error) {
|
||||||
|
return strconv.Atoi(internal.BytesToString(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseInt(b []byte, base int, bitSize int) (int64, error) {
|
||||||
|
return strconv.ParseInt(internal.BytesToString(b), base, bitSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseUint(b []byte, base int, bitSize int) (uint64, error) {
|
||||||
|
return strconv.ParseUint(internal.BytesToString(b), base, bitSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseFloat(b []byte, bitSize int) (float64, error) {
|
||||||
|
return strconv.ParseFloat(internal.BytesToString(b), bitSize)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,90 +3,89 @@ package proto
|
||||||
import (
|
import (
|
||||||
"encoding"
|
"encoding"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"gopkg.in/redis.v5/internal"
|
"gopkg.in/redis.v5/internal"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Scan(s string, v interface{}) error {
|
func Scan(b []byte, v interface{}) error {
|
||||||
switch v := v.(type) {
|
switch v := v.(type) {
|
||||||
case nil:
|
case nil:
|
||||||
return internal.RedisError("redis: Scan(nil)")
|
return internal.RedisError("redis: Scan(nil)")
|
||||||
case *string:
|
case *string:
|
||||||
*v = s
|
*v = internal.BytesToString(b)
|
||||||
return nil
|
return nil
|
||||||
case *[]byte:
|
case *[]byte:
|
||||||
*v = []byte(s)
|
*v = b
|
||||||
return nil
|
return nil
|
||||||
case *int:
|
case *int:
|
||||||
var err error
|
var err error
|
||||||
*v, err = strconv.Atoi(s)
|
*v, err = atoi(b)
|
||||||
return err
|
return err
|
||||||
case *int8:
|
case *int8:
|
||||||
n, err := strconv.ParseInt(s, 10, 8)
|
n, err := parseInt(b, 10, 8)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*v = int8(n)
|
*v = int8(n)
|
||||||
return nil
|
return nil
|
||||||
case *int16:
|
case *int16:
|
||||||
n, err := strconv.ParseInt(s, 10, 16)
|
n, err := parseInt(b, 10, 16)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*v = int16(n)
|
*v = int16(n)
|
||||||
return nil
|
return nil
|
||||||
case *int32:
|
case *int32:
|
||||||
n, err := strconv.ParseInt(s, 10, 32)
|
n, err := parseInt(b, 10, 32)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*v = int32(n)
|
*v = int32(n)
|
||||||
return nil
|
return nil
|
||||||
case *int64:
|
case *int64:
|
||||||
n, err := strconv.ParseInt(s, 10, 64)
|
n, err := parseInt(b, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*v = n
|
*v = n
|
||||||
return nil
|
return nil
|
||||||
case *uint:
|
case *uint:
|
||||||
n, err := strconv.ParseUint(s, 10, 64)
|
n, err := parseUint(b, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*v = uint(n)
|
*v = uint(n)
|
||||||
return nil
|
return nil
|
||||||
case *uint8:
|
case *uint8:
|
||||||
n, err := strconv.ParseUint(s, 10, 8)
|
n, err := parseUint(b, 10, 8)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*v = uint8(n)
|
*v = uint8(n)
|
||||||
return nil
|
return nil
|
||||||
case *uint16:
|
case *uint16:
|
||||||
n, err := strconv.ParseUint(s, 10, 16)
|
n, err := parseUint(b, 10, 16)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*v = uint16(n)
|
*v = uint16(n)
|
||||||
return nil
|
return nil
|
||||||
case *uint32:
|
case *uint32:
|
||||||
n, err := strconv.ParseUint(s, 10, 32)
|
n, err := parseUint(b, 10, 32)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*v = uint32(n)
|
*v = uint32(n)
|
||||||
return nil
|
return nil
|
||||||
case *uint64:
|
case *uint64:
|
||||||
n, err := strconv.ParseUint(s, 10, 64)
|
n, err := parseUint(b, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*v = n
|
*v = n
|
||||||
return nil
|
return nil
|
||||||
case *float32:
|
case *float32:
|
||||||
n, err := strconv.ParseFloat(s, 32)
|
n, err := parseFloat(b, 32)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -94,13 +93,13 @@ func Scan(s string, v interface{}) error {
|
||||||
return err
|
return err
|
||||||
case *float64:
|
case *float64:
|
||||||
var err error
|
var err error
|
||||||
*v, err = strconv.ParseFloat(s, 64)
|
*v, err = parseFloat(b, 64)
|
||||||
return err
|
return err
|
||||||
case *bool:
|
case *bool:
|
||||||
*v = len(s) == 1 && s[0] == '1'
|
*v = len(b) == 1 && b[0] == '1'
|
||||||
return nil
|
return nil
|
||||||
case encoding.BinaryUnmarshaler:
|
case encoding.BinaryUnmarshaler:
|
||||||
return v.UnmarshalBinary([]byte(s))
|
return v.UnmarshalBinary(b)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
"redis: can't unmarshal %T (consider implementing BinaryUnmarshaler)", v)
|
"redis: can't unmarshal %T (consider implementing BinaryUnmarshaler)", v)
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
// +build appengine
|
||||||
|
|
||||||
|
package internal
|
||||||
|
|
||||||
|
func BytesToString(b []byte) string {
|
||||||
|
return string(b)
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
// +build !appengine
|
||||||
|
|
||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
func BytesToString(b []byte) string {
|
||||||
|
bytesHeader := (*reflect.SliceHeader)(unsafe.Pointer(&b))
|
||||||
|
strHeader := reflect.StringHeader{bytesHeader.Data, bytesHeader.Len}
|
||||||
|
return *(*string)(unsafe.Pointer(&strHeader))
|
||||||
|
}
|
|
@ -13,7 +13,7 @@ func ToLower(s string) string {
|
||||||
}
|
}
|
||||||
b[i] = c
|
b[i] = c
|
||||||
}
|
}
|
||||||
return string(b)
|
return BytesToString(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func isLower(s string) bool {
|
func isLower(s string) bool {
|
||||||
|
|
14
parser.go
14
parser.go
|
@ -386,22 +386,12 @@ func timeParser(rd *proto.Reader, n int64) (interface{}, error) {
|
||||||
return nil, fmt.Errorf("got %d elements, expected 2", n)
|
return nil, fmt.Errorf("got %d elements, expected 2", n)
|
||||||
}
|
}
|
||||||
|
|
||||||
secStr, err := rd.ReadStringReply()
|
sec, err := rd.ReadInt()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
microsecStr, err := rd.ReadStringReply()
|
microsec, err := rd.ReadInt()
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
sec, err := strconv.ParseInt(secStr, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
microsec, err := strconv.ParseInt(microsecStr, 10, 64)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ func NewBoolResult(val bool, err error) *BoolCmd {
|
||||||
// NewStringResult returns a StringCmd initalised with val and err for testing
|
// NewStringResult returns a StringCmd initalised with val and err for testing
|
||||||
func NewStringResult(val string, err error) *StringCmd {
|
func NewStringResult(val string, err error) *StringCmd {
|
||||||
var cmd StringCmd
|
var cmd StringCmd
|
||||||
cmd.val = val
|
cmd.val = []byte(val)
|
||||||
cmd.setErr(err)
|
cmd.setErr(err)
|
||||||
return &cmd
|
return &cmd
|
||||||
}
|
}
|
||||||
|
|
4
ring.go
4
ring.go
|
@ -265,7 +265,7 @@ func (c *Ring) shardByName(name string) (*ringShard, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Ring) cmdShard(cmd Cmder) (*ringShard, error) {
|
func (c *Ring) cmdShard(cmd Cmder) (*ringShard, error) {
|
||||||
cmdInfo := c.cmdInfo(cmd.arg(0))
|
cmdInfo := c.cmdInfo(cmd.name())
|
||||||
firstKey := cmd.arg(cmdFirstKeyPos(cmd, cmdInfo))
|
firstKey := cmd.arg(cmdFirstKeyPos(cmd, cmdInfo))
|
||||||
return c.shardByKey(firstKey)
|
return c.shardByKey(firstKey)
|
||||||
}
|
}
|
||||||
|
@ -364,7 +364,7 @@ func (c *Ring) Pipelined(fn func(*Pipeline) error) ([]Cmder, error) {
|
||||||
func (c *Ring) pipelineExec(cmds []Cmder) (firstErr error) {
|
func (c *Ring) pipelineExec(cmds []Cmder) (firstErr error) {
|
||||||
cmdsMap := make(map[string][]Cmder)
|
cmdsMap := make(map[string][]Cmder)
|
||||||
for _, cmd := range cmds {
|
for _, cmd := range cmds {
|
||||||
cmdInfo := c.cmdInfo(cmd.arg(0))
|
cmdInfo := c.cmdInfo(cmd.name())
|
||||||
name := cmd.arg(cmdFirstKeyPos(cmd, cmdInfo))
|
name := cmd.arg(cmdFirstKeyPos(cmd, cmdInfo))
|
||||||
if name != "" {
|
if name != "" {
|
||||||
name = c.hash.Get(hashtag.Key(name))
|
name = c.hash.Get(hashtag.Key(name))
|
||||||
|
|
Loading…
Reference in New Issue