Как использовать контекст, если в одном методе используется несколько транзакций

«Как использовать контекст, если в одном методе используется несколько транзакций» — вопрос из категории Golang, который задают на 23% собеседований Golang Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

func ProcessWithTransactions(ctx context.Context, db *sql.DB) error {
    // Первая транзакция
    tx1, err := db.BeginTx(ctx, nil)
    if err != nil {
        return err
    }
    defer tx1.Rollback()

    // Работа с tx1
    if _, err := tx1.ExecContext(ctx, "INSERT..."); err != nil {
        return err
    }

    // Вторая транзакция (используем тот же контекст)
    tx2, err := db.BeginTx(ctx, nil)
    if err != nil {
        return err
    }
    defer tx2.Rollback()

    // Работа с tx2
    if _, err := tx2.ExecContext(ctx, "UPDATE..."); err != nil {
        return err
    }

    // Коммиты только если все успешно
    if err := tx1.Commit(); err != nil {
        return err
    }
    return tx2.Commit()
}

Ключевые моменты:

  1. Передаем один контекст во все транзакции
  2. Каждая транзакция должна иметь свой Rollback
  3. Коммитить только после успешного выполнения всех операций
  4. Контекст будет распространяться на все операции внутри транзакций