Извиняюсь, если это уже спрашивали. Во-первых, позвольте мне показать, как воспроизвести мою проблему:
> SET test 10
func main() {
redisClient := getConnection() // Abstracting get connection for simplicity
r, err := redisClient.Do("HSET", "test", "f1", "v1", "f2", "v2")
fmt.Printf("%+v e: %+v\n")
}
Честно говоря, на этом шаге отображается следующая ошибка (это означает err != nil):
WRONGTYPE Operation against a key holding the wrong kind of value e: WRONGTYPE Operation against a key holding the wrong kind of value
func main() {
redisClient := getConnection()
redisClient.Send("MULTI")
redisClient.Send("HSET", "test", "f1", "v1", "f2", "v2")
r, err := redisClient.Do("EXEC")
fmt.Printf("%+v e: %+v\n")
}
Печатается строка:
WRONGTYPE Operation against a key holding the wrong kind of value e: <nil>
Мне это кажется непоследовательным, так как я ожидаю, что MULTI также вернет WRONGTYPE в переменной ошибки.
Это преднамеренное поведение или я что-то упустил?

Для каждой команды в транзакции Redis есть два результата. Один результат добавления команды в транзакцию, а другой результат выполнения команды в транзакции.
Метод Do возвращает результат добавления команды в транзакцию.
Команда Redis EXEC возвращает массив, каждый элемент которого является результатом выполнения команды в транзакции. Изучите каждый элемент, чтобы проверить отдельные ошибки команды:
values, err := redis.Values(redisClient.Do("EXEC"))
if err != nil {
// Handle error
}
if err, ok := values[0].(redis.Error); ok {
// Handle error for command 0.
// Adjust the index to match the actual index of
// of the HMSET command in the transaction.
}
Может быть полезна вспомогательная функция для проверки ошибок команды транзакции:
func execValues(reply interface{}, err error) ([]interface{}, error) {
if err != nil {
return nil, err
}
values, ok := reply.([]interface{})
if !ok {
return nil, fmt.Errorf("unexpected type for EXEC reply, got type %T", reply)
}
for _, v := range values {
if err, ok := v.(redis.Error); ok {
return values, err
}
}
return values, nil
}
Используйте это так:
values, err := execValues(redisClient.Do("EXEC"))
if err != nil {
// Handle error.
}
@Rick Do возвращает ошибку добавления команды в транзакцию. Изучите результат EXEC, чтобы получить ошибку выполнения команды в транзакции.
Спасибо. Я попробую позже сегодня. Однако меня смущает то, что в документации указано, что «если какой-либо из полученных ответов является ошибкой, то Do возвращает ошибку» (pkg.go.dev/github.com/gomodule/redigo/redis#hdr-Pipelining ). Это наводит меня на мысль, что если какая-либо команда завершится ошибкой, я должен получить ошибку при выполнении
Do("EXEC").