Procházet zdrojové kódy

fix: reformate code

runningwater před 3 měsíci
rodič
revize
ceed43a94f

+ 13 - 1
database/db.go

@@ -13,6 +13,7 @@ import (
 	"github.com/runningwater/go-redis/resp/reply"
 )
 
+// DB 数据库
 type DB struct {
 	index int
 	data  dict.Dict
@@ -28,10 +29,21 @@ func NewDB() *DB {
 	}
 }
 
+// Exec 执行一个redis命令
+// 参数:
+//   - c: 客户端连接对象,表示发送命令的客户端连接
+//   - cmdLine: 命令行参数,包含命令名称和所有参数的字节切片
+//
+// 返回值:
+//   - resp.Reply: 命令执行结果的回复
 func (d *DB) Exec(c resp.Connection, cmdLine CmdLine) resp.Reply {
+	// 检查命令行参数是否为空
+	if len(cmdLine) == 0 {
+		return reply.NewErrReply("empty command")
+	}
 	// ping set setnx get
 	cmdName := strings.ToLower(string(cmdLine[0]))
-	// 查表
+	// 查找命令
 	cmd, ok := cmdTable[cmdName]
 	if !ok {
 		return reply.NewUnknownErrReply(cmdName)

+ 8 - 1
resp/connection/conn.go

@@ -1,6 +1,6 @@
 // Author: simon (ynwdlxm@163.com)
 // Date: 2025/9/12 11:02
-// Desc: 对每个连接进行封装(第个客服连接的描述)
+// Desc: Encapsulation of each connection (description of each client connection)
 
 package connection
 
@@ -13,6 +13,7 @@ import (
 	"github.com/runningwater/go-redis/lib/sync/wait"
 )
 
+// Connection represents a client connection to the Redis server
 type Connection struct {
 	conn       net.Conn
 	waiting    wait.Wait
@@ -20,16 +21,19 @@ type Connection struct {
 	selectedDB int
 }
 
+// NewConnection creates a new connection wrapper
 func NewConnection(conn net.Conn) *Connection {
 	return &Connection{
 		conn: conn,
 	}
 }
 
+// RemoteAddr returns the remote network address
 func (c *Connection) RemoteAddr() net.Addr {
 	return c.conn.RemoteAddr()
 }
 
+// Close closes the connection
 func (c *Connection) Close() error {
 	timeout := c.waiting.WaitWithTimeout(10 * time.Second)
 	if timeout {
@@ -41,6 +45,7 @@ func (c *Connection) Close() error {
 	return err
 }
 
+// Write writes data to the connection
 func (c *Connection) Write(bytes []byte) error {
 	if len(bytes) == 0 {
 		return nil
@@ -56,10 +61,12 @@ func (c *Connection) Write(bytes []byte) error {
 	return err
 }
 
+// GetDBIndex returns the currently selected database index
 func (c *Connection) GetDBIndex() int {
 	return c.selectedDB
 }
 
+// SelectDB selects a database
 func (c *Connection) SelectDB(dbNum int) {
 	c.selectedDB = dbNum
 }

+ 22 - 21
resp/handler/handler.go

@@ -1,6 +1,6 @@
 // Author: simon (ynwdlxm@163.com)
 // Date: 2025/9/12 13:24
-// Desc: 处理 RESP 协议
+// Desc: Handling RESP protocol
 
 package handler
 
@@ -21,33 +21,34 @@ import (
 	"github.com/runningwater/go-redis/resp/reply"
 )
 
+// RespHandler handles client connections and RESP protocol
 type RespHandler struct {
 	activeConn sync.Map
 	db         dbface.Database
 	closing    atomic.Boolean
 }
 
+// NewHandler creates a new RespHandler
 func NewHandler() *RespHandler {
-	// var db dbface.Database
-	// var db = database.NewEchoDatabase()
-
 	return &RespHandler{
 		db: database.NewEchoDatabase(),
 	}
 }
 
+// Handle processes client connections
 func (r *RespHandler) Handle(ctx context.Context, conn net.Conn) {
 	if r.closing.Get() {
 		_ = conn.Close()
+		return
 	}
 	logger.Info("new connection from ", conn.RemoteAddr().String())
 	client := connection.NewConnection(conn)
 	r.activeConn.Store(client, struct{}{})
 
-	// 解析数据
+	// Parse data
 	ch := parser.ParseStream(conn)
 	for payload := range ch {
-		logger.Info("收到 通道数据: ", payload)
+		logger.Info("received channel data: ", payload)
 		// error
 		if payload.Err != nil {
 			if errors.Is(payload.Err, io.EOF) ||
@@ -57,11 +58,11 @@ func (r *RespHandler) Handle(ctx context.Context, conn net.Conn) {
 				logger.Info("connection closed: ", client.RemoteAddr().String())
 				return
 			}
-			// 协议错误
-			logger.Error("协议错误: ", payload.Err.Error())
-			errReplay := reply.NewErrReply(payload.Err.Error())
+			// Protocol error
+			logger.Error("protocol error: ", payload.Err.Error())
+			errReply := reply.NewErrReply(payload.Err.Error())
 
-			err := client.Write(errReplay.ToBytes())
+			err := client.Write(errReply.ToBytes())
 			if err != nil {
 				r.closeClient(client)
 				logger.Error("client.Write:", err.Error())
@@ -80,27 +81,27 @@ func (r *RespHandler) Handle(ctx context.Context, conn net.Conn) {
 			logger.Error("require multi bulk reply")
 			continue
 		}
-		// 命令执行
+		// Command execution
 		execResult := r.db.Exec(client, bulkReply.Args)
 		if execResult == nil {
 			execResult = reply.NewUnknownErrReply("aa")
 		}
-		// 返回结果
+		// Return result
 		logger.Info("exec result: ", execResult)
 
 		_ = client.Write(execResult.ToBytes())
 
-	} //  for end
+	} // for end
 }
 
-// Close 关闭RespHandler处理器,释放相关资源
-// 该函数会关闭所有活跃连接并关闭数据库连接
-// 返回值: error - 关闭操作的错误信息,目前始终返回nil
+// Close shuts down the RespHandler and releases resources
+// This function closes all active connections and the database connection
+// Return value: error - Error information for the close operation, currently always returns nil
 func (r *RespHandler) Close() error {
 	logger.Info("handler shutting down...")
 	r.closing.Set(true)
 
-	// 遍历所有活跃连接并关闭它们
+	// Iterate through all active connections and close them
 	r.activeConn.Range(
 		func(key, value any) bool {
 			client := key.(*connection.Connection)
@@ -108,16 +109,16 @@ func (r *RespHandler) Close() error {
 			return true
 		})
 
-	// 关闭数据库连接
+	// Close database connection
 	r.db.Close()
 
 	return nil
 }
 
-// closeClient 关闭客户端连接
-// 参数:
+// closeClient closes a client connection
+// Parameters:
 //
-//	client *connection.Connection - 需要关闭的客户端连接对象
+//	client *connection.Connection - The client connection object to close
 func (r *RespHandler) closeClient(client *connection.Connection) {
 	_ = client.Close()
 	r.db.AfterClientClose(client)

+ 71 - 76
resp/parser/parser.go

@@ -1,8 +1,8 @@
 // Author: simon (ynwdlxm@163.com)
 // Date: 2025/7/11 15:58
-// Desc: 解析器
+// Desc: Parser for Redis protocol
 //
-// 解析器用于将Redis协议的字节流解析为抽象的响应对象
+// The parser is used to parse the byte stream of the Redis protocol into abstract response objects
 
 package parser
 
@@ -20,11 +20,11 @@ import (
 	"github.com/runningwater/go-redis/resp/reply"
 )
 
-// Payload 解析器的载荷
-// 用于存储解析器的状态信息
+// Payload is the payload of the parser
+// Used to store the state information of the parser
 type Payload struct {
-	Data resp.Reply // 解析后的响应对象, 与返回数据结构一致
-	Err  error      // 解析过程中发生的错误
+	Data resp.Reply // Parsed response object, consistent with the return data structure
+	Err  error      // Errors that occurred during parsing
 }
 
 func (p *Payload) String() string {
@@ -32,27 +32,27 @@ func (p *Payload) String() string {
 }
 
 type currentState struct {
-	readingMultiLine  bool     // 是否正在读取多行数据
-	expectedArgsCount int      // 期望的参数数量
-	msgType           byte     // 消息类型
-	args              [][]byte // 参数列表
-	bulkLen           int64    // 批量数据的长度
+	readingMultiLine  bool     // Whether multi-line data is being read
+	expectedArgsCount int      // Expected number of arguments
+	msgType           byte     // Message type
+	args              [][]byte // Argument list
+	bulkLen           int64    // Length of bulk data
 }
 
 func (s *currentState) finished() bool {
 	return s.expectedArgsCount > 0 && len(s.args) == s.expectedArgsCount
 }
 
-// ParseStream 解析输入流中的数据
-// 解析器会根据Redis协议的规则解析输入流中的数据
-// 解析后的结果会通过通道发送给调用方
-// 参数:
+// ParseStream parses data in the input stream
+// The parser parses the data in the input stream according to the rules of the Redis protocol
+// The parsed results will be sent to the caller through the channel
+// Parameters:
 //
-//	reader io.Reader - 输入流读取器
+//	reader io.Reader - Input stream reader
 //
-// 返回值:
+// Return value:
 //
-//	<-chan *Payload - 解析结果通道,每个元素都是一个解析后的Payload对象
+//	<-chan *Payload - Parse result channel, each element is a parsed Payload object
 func ParseStream(reader io.Reader) <-chan *Payload {
 	logger.Debug("parse stream...")
 	ch := make(chan *Payload)
@@ -70,26 +70,23 @@ func parse0(reader io.Reader, ch chan<- *Payload) {
 	bufReader := bufio.NewReader(reader)
 	var state currentState
 	var err error
-	var line []byte // 一行数据
-	for {           // 死循环
+	var line []byte // A line of data
+	for {           // Infinite loop
 		var ioErr bool
 		line, ioErr, err = readLine(bufReader, &state)
 		if err != nil {
+			ch <- &Payload{
+				Err: err,
+			}
 			if ioErr {
-				ch <- &Payload{
-					Err: err,
-				}
 				close(ch)
 				return
 			}
-			ch <- &Payload{
-				Err: err,
-			}
-			state = currentState{} // 重置状态
+			state = currentState{} // Reset state
 			continue
 		}
 
-		// 判断是不是多行模式
+		// Check if it is multi-line mode
 		if !state.readingMultiLine {
 			if line[0] == '*' { // *3/r/n
 				err = parseMultiBulkHeader(line, &state)
@@ -97,14 +94,14 @@ func parse0(reader io.Reader, ch chan<- *Payload) {
 					ch <- &Payload{
 						Err: errors.New("protocol error: " + string(line)),
 					}
-					state = currentState{} // 重置状态
+					state = currentState{} // Reset state
 					continue
 				}
 				if state.expectedArgsCount == 0 {
 					ch <- &Payload{
 						Data: reply.NewEmptyMultiBulkReply(),
 					}
-					state = currentState{} // 重置状态
+					state = currentState{} // Reset state
 					continue
 				}
 			} else if line[0] == '$' { // $3/r/n
@@ -113,7 +110,7 @@ func parse0(reader io.Reader, ch chan<- *Payload) {
 					ch <- &Payload{
 						Err: errors.New("protocol error: " + string(line)),
 					}
-					state = currentState{} // 重置状态
+					state = currentState{} // Reset state
 					continue
 				}
 				// $-1\r\n
@@ -121,7 +118,7 @@ func parse0(reader io.Reader, ch chan<- *Payload) {
 					ch <- &Payload{
 						Data: reply.NewNullBulkReply(),
 					}
-					state = currentState{} // 重置状态
+					state = currentState{} // Reset state
 					continue
 				}
 			} else {
@@ -135,7 +132,7 @@ func parse0(reader io.Reader, ch chan<- *Payload) {
 				continue
 			}
 		} else {
-			// 解析多行模式
+			// Parse multi-line mode
 			err = readBody(line, &state)
 			if err != nil {
 				ch <- &Payload{
@@ -154,62 +151,60 @@ func parse0(reader io.Reader, ch chan<- *Payload) {
 				}
 				ch <- &Payload{
 					Data: result,
-					Err:  err,
 				}
-				state = currentState{} // 重置状态
+				state = currentState{} // Reset state
 			}
 		}
 	} // End for true
 }
 
-// 读取一行数据
-// 读取到的数据可能是完整的一行,也可能是不完整的一行
+// Read a line of data
+// The read data may be a complete line or an incomplete line
 //
-//	返回值:
-//	1. 读取到的数据
-//	2. 是否读取到了不完整的一行
-//	3. 错误信息
-//	例如: *3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n
-//	读取到的数据可能是: *3\r\n, $3\r\nSET\r\n, $3\r\nkey\r\n, $5\r\nvalue\r\n
-//	读取到的数据可能是: *3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n
+// Return values:
+// 1. Data read
+// 2. Whether an incomplete line was read
+// 3. Error message
+// For example: *3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n
+// The data read may be: *3\r\n, $3\r\nSET\r\n, $3\r\nkey\r\n, $5\r\nvalue\r\n
+// The data read may be: *3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n
 func readLine(reader *bufio.Reader, state *currentState) ([]byte, bool, error) {
 	var msg []byte
 	var err error
-	if state.bulkLen == 0 { // \r\n 切分
-		// 读取一行数据
-		reader.Reset(reader)
+	if state.bulkLen == 0 { // \r\n split
+		// Read a line of data
 		msg, err = reader.ReadBytes('\n')
 		logger.Info("\r\n***readLine: ", string(msg))
 		if err != nil {
 			return nil, true, err
 		}
-		// 不是 \r\n 结尾的数据
+		// Data that does not end with \r\n
 		if len(msg) == 0 || msg[len(msg)-2] != '\r' {
 			return nil, false, errors.New("readLine-protocol error: " + string(msg))
 		}
 
 	} else {
-		// ELSE 之前读取到了 $数字,严格读取数字个字节
+		// ELSE previously read $number, strictly read number of bytes
 		msg = make([]byte, state.bulkLen+2)
 		_, err := io.ReadFull(reader, msg)
 		if err != nil {
 			return nil, true, err
 		}
-		// 不是 \r\n 结尾的数据
+		// Data that does not end with \r\n
 		if len(msg) == 0 || msg[len(msg)-2] != '\r' || msg[len(msg)-1] != '\n' {
 			return nil, false, errors.New("readLine-protocol error: " + string(msg))
 		}
 
-		// 重置 bulkLen
+		// Reset bulkLen
 		state.bulkLen = 0
 	}
 	return msg, false, nil
 }
 
-// 解析串的头部信息
+// Parse the header information of the string
 //
-//	例如: *3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n
-//	解析为: *3\r\n
+// For example: *3\r\n$3\r\nSET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n
+// Parsed as: *3\r\n
 func parseMultiBulkHeader(msg []byte, state *currentState) error {
 	var err error
 	var expectedLine uint64
@@ -231,12 +226,12 @@ func parseMultiBulkHeader(msg []byte, state *currentState) error {
 	}
 }
 
-// 单行字符串
+// Single line string
 //
-//	$4\r\nPING\r\n
+// $4\r\nPING\r\n
 func parseBulkHeader(msg []byte, state *currentState) error {
 	var err error
-	// $ 开头的行,读取 bulkLen
+	// $ Start line, read bulkLen
 	state.bulkLen, err = strconv.ParseInt(string(msg[1:len(msg)-2]), 10, 64)
 	if err != nil {
 		return errors.New("protocol error: " + string(msg))
@@ -255,14 +250,14 @@ func parseBulkHeader(msg []byte, state *currentState) error {
 	}
 }
 
-// 解析单行回复
+// Parse single line reply
 //
-//	例如
-//	+OK\r\n
-//	-err\r\n
-//	:1\r\n
+// For example
+// +OK\r\n
+// -err\r\n
+// :1\r\n
 func parseSingleLineReply(msg []byte) (resp.Reply, error) {
-	str := strings.TrimSuffix(string(msg), "\r\n") // 去除 \r\n
+	str := strings.TrimSuffix(string(msg), "\r\n") // Remove \r\n
 
 	var result resp.Reply
 	switch msg[0] {
@@ -282,38 +277,38 @@ func parseSingleLineReply(msg []byte) (resp.Reply, error) {
 	return result, nil
 }
 
-// readBody 解析Redis协议中的消息体部分,处理以$开头的bulk字符串或普通字符串
+// readBody parses the message body part in the Redis protocol, handling bulk strings starting with $ or ordinary strings
 //
-//	例如
-//	 PING\r\n
-//	 SET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n
+// For example
+// PING\r\n
+// SET\r\n$3\r\nkey\r\n$5\r\nvalue\r\n
 //
-// 参数:
+// Parameters:
 //
-//	msg: 完整的消息字节切片,包含\r\n结尾
-//	state: 当前解析状态的指针,用于存储解析结果
+//	msg: Complete message byte slice, including \r\n ending
+//	state: Pointer to current parsing state, used to store parsing results
 //
-// 返回值:
+// Return value:
 //
-//	error: 解析过程中出现的错误,如协议格式错误等
+//	error: Errors that occurred during parsing, such as protocol format errors, etc.
 func readBody(msg []byte, state *currentState) error {
-	line := msg[:len(msg)-2] // 去除 \r\n
+	line := msg[0 : len(msg)-2] // Remove \r\n
 
 	var err error
 
-	// 处理以$开头的bulk字符串格式
+	// Handle bulk string format starting with $
 	if line[0] == '$' {
 		state.bulkLen, err = strconv.ParseInt(string(line[1:]), 10, 64)
 		if err != nil {
 			return errors.New("protocol error: " + string(msg))
 		}
-		// 处理空字符串情况,$0\r\n表示空字符串
+		// Handle empty string case, $0\r\n represents empty string
 		if state.bulkLen <= 0 {
 			state.args = append(state.args, []byte{})
 			state.bulkLen = 0
 		}
 	} else {
-		// 处理普通字符串,直接添加到参数列表中
+		// Handle ordinary strings, directly add to argument list
 		state.args = append(state.args, line)
 	}
 	return nil

+ 10 - 2
resp/reply/consts.go

@@ -58,7 +58,7 @@ func NewNoReply() *NoReply {
 	return &NoReply{}
 }
 
-// NullBulkReply 表示NO响应,用于Redis协议的NO响应
+// NullBulkReply 表示NULL响应,用于Redis协议的NULL响应
 // 返回格式:"$-1\r\n"
 type NullBulkReply struct{}
 
@@ -66,11 +66,12 @@ func (n NullBulkReply) String() string {
 	return "$-1\r\n"
 }
 
-// ToBytes 将NO响应转换为字节数组
+// ToBytes 将NULL响应转换为字节数组
 // 返回格式:"$-1\r\n"
 func (n NullBulkReply) ToBytes() []byte {
 	return []byte("$-1\r\n")
 }
+
 func NewNullBulkReply() *NullBulkReply {
 	return &NullBulkReply{}
 }
@@ -87,6 +88,13 @@ func (e EmptyMultiBulkReply) String() string {
 func (e EmptyMultiBulkReply) ToBytes() []byte {
 	return []byte("*0\r\n")
 }
+
 func NewEmptyMultiBulkReply() *EmptyMultiBulkReply {
 	return &EmptyMultiBulkReply{}
 }
+
+// IsOkReply 判断回复是否为OK响应
+func IsOkReply(reply interface{}) bool {
+	_, ok := reply.(*OkReply)
+	return ok
+}

+ 4 - 0
resp/reply/error.go

@@ -76,6 +76,10 @@ func (w *WrongTypeErrReply) Error() string {
 	return "WRONG TYPE Operation against a key holding the wrong kind of value"
 }
 
+func (w *WrongTypeErrReply) String() string {
+	return w.Error()
+}
+
 func (w *WrongTypeErrReply) ToBytes() []byte {
 	return []byte("-WRONG TYPE Operation against a key holding the wrong kind of value\r\n")
 }

+ 37 - 30
resp/reply/reply.go

@@ -1,25 +1,25 @@
-// Package reply 实现了Redis序列化协议(RESP)的回复处理功能。
+// Package reply implements the Redis Serialization Protocol (RESP) reply handling functionality.
 //
-// 本包包含构建符合Redis RESP协议的各种响应格式的实现,支持以下类型:
-//   - 简单字符串(Simple Strings:  StatusReply
-//   - 错误类型(Errors):            StandardErrReply 及其子类型
-//   - 整型(Integers:             IntReply
-//   - 批量字符串(Bulk Strings:    BulkReply
-//   - 数组(Arrays:               MultiBulkReply
+// This package contains implementations for building various response formats that comply with the Redis RESP protocol, supporting the following types:
+//   - Simple Strings:  StatusReply
+//   - Errors:          StandardErrReply and its subtypes
+//   - Integers:        IntReply
+//   - Bulk Strings:    BulkReply
+//   - Arrays:          MultiBulkReply
 //
-// 所有回复类型都实现了 `resp.Reply` 接口,通过 `ToBytes()` 方法生成符合RESP协议格式的字节数据。
+// All reply types implement the [resp.Reply](file:///Users/lixiaoming/go/src/github.com/runningwater/go-redis/interface/resp/reply.go#L7-L12) interface, generating byte data in the RESP protocol format through the [ToBytes()](file:///Users/lixiaoming/go/src/github.com/runningwater/go-redis/interface/resp/reply.go#L9-L9) method.
 //
-// 示例用法:
+// Example usage:
 //
-// 创建整数回复
+// Create an integer reply
 //
 //	reply := NewIntReply(42)
-//	output := reply.ToBytes() // 输出 ":42\r\n"
+//	output := reply.ToBytes() // Output ":42\r\n"
 //
-// 创建批量字符串回复
+// Create a bulk string reply
 //
 //	bulk := NewBulkReply([]byte("hello"))
-//	output := bulk.ToBytes() // 输出 "$5\r\nhello\r\n"
+//	output := bulk.ToBytes() // Output "$5\r\nhello\r\n"
 package reply
 
 import (
@@ -34,7 +34,7 @@ var (
 	CRLF               = "\r\n"
 )
 
-// BulkReply 表示批量字符串回复的结构体。
+// BulkReply represents a bulk string reply structure.
 type BulkReply struct {
 	Arg []byte // "test" => "$4\r\ntest\r\n"
 }
@@ -50,11 +50,12 @@ func (b *BulkReply) ToBytes() []byte {
 	return []byte("$" + strconv.Itoa(len(b.Arg)) + CRLF + string(b.Arg) + CRLF)
 }
 
+// NewBulkReply creates a new bulk reply
 func NewBulkReply(arg []byte) *BulkReply {
 	return &BulkReply{Arg: arg}
 }
 
-// MultiBulkReply 表示多条批量字符串回复的结构体。 数组
+// MultiBulkReply represents a multi-bulk string reply structure.
 type MultiBulkReply struct {
 	Args [][]byte
 }
@@ -78,14 +79,15 @@ func (m *MultiBulkReply) ToBytes() []byte {
 	return buf.Bytes()
 }
 
+// NewMultiBulkReply creates a new multi-bulk reply
 func NewMultiBulkReply(args [][]byte) *MultiBulkReply {
 	return &MultiBulkReply{Args: args}
 }
 
-// StatusReply 表示简单字符串回复的结构体。
-// 例如:OK、PING、SET、GET等命令的回复。
-// 对应Redis的"+"开头的回复。
-// 例如:"+OK\r\n"
+// StatusReply represents a simple string reply structure.
+// For example: OK, PING, SET, GET command replies.
+// Corresponds to Redis replies starting with "+".
+// For example: "+OK\r\n"
 type StatusReply struct {
 	Status string
 }
@@ -98,13 +100,14 @@ func (s *StatusReply) ToBytes() []byte {
 	return []byte("+" + s.Status + CRLF)
 }
 
+// NewStatusReply creates a new status reply
 func NewStatusReply(status string) *StatusReply {
 	return &StatusReply{Status: status}
 }
 
-// IntReply 表示整数回复的结构体。
-// 对应Redis的":"开头的回复。
-// 例如:":1\r\n"
+// IntReply represents an integer reply structure.
+// Corresponds to Redis replies starting with ":".
+// For example: ":1\r\n"
 type IntReply struct {
 	Code int64
 }
@@ -116,19 +119,21 @@ func (i *IntReply) String() string {
 func (i *IntReply) ToBytes() []byte {
 	return []byte(":" + strconv.FormatInt(i.Code, 10) + CRLF)
 }
+
+// NewIntReply creates a new integer reply
 func NewIntReply(code int64) *IntReply {
 	return &IntReply{Code: code}
 }
 
-// ErrorReply 表示错误回复的接口。
+// ErrorReply represents an error reply interface.
 type ErrorReply interface {
 	Error() string
 	ToBytes() []byte
 }
 
-// StandardErrReply 表示标准错误回复的结构体。
-// 对应Redis的"-"开头的回复。
-// 例如:"-ERR unknown command 'foobar'\r\n"
+// StandardErrReply represents a standard error reply structure.
+// Corresponds to Redis replies starting with "-".
+// For example: "-ERR unknown command 'foobar'\r\n"
 type StandardErrReply struct {
 	Status string
 }
@@ -145,13 +150,15 @@ func (s *StandardErrReply) ToBytes() []byte {
 	return []byte("-" + s.Status + CRLF)
 }
 
+// NewErrReply creates a new error reply
 func NewErrReply(status string) *StandardErrReply {
 	return &StandardErrReply{Status: status}
 }
 
-// IsErrReply 判断回复是否为错误回复。
-// 错误回复的第一个字节为"-"。
-// 例如:"-ERR unknown command 'foobar'\r\n"
+// IsErrReply checks if the reply is an error reply.
+// Error replies start with "-".
+// For example: "-ERR unknown command 'foobar'\r\n"
 func IsErrReply(reply resp.Reply) bool {
-	return reply.ToBytes()[0] == '-'
+	toBytes := reply.ToBytes()
+	return len(toBytes) > 0 && toBytes[0] == '-'
 }