I'd like input on whether the following idea is good or bad, and why. Consider an abstract transaction, modeled as follows: func Transaction(ctx context.Context, body func(ctx context.Context) error) error func OnCommit(ctx context.Context, commitHook func(ctx context.Context)) func OnRollback(ctx context.Context, rollbackHook func(ctx context.Context))
The code that wishes to execute a transaction would call Transaction and provide the body of the transaction as a function parameter. If that function returns an error, the transaction is rolled back, by calling any hooks registered during that transaction by calling OnRollback. If the body function returns success, the transaction is committed by calling any hooks registered during that transaction by calling OnCommit. The implication of this model is that the identity of what transaction you're in is stored in the context. The ctx passed into body has that value added to it, and the OnCommit and OnRollback calls associate the hooks with the transaction they find in the context. Of course the same thing could be done by passing the transaction explicitly, e.g. func Transaction(ctx context.Context, body func(ctx context.Context, tx Tx) error) error func OnCommit(tx Tx, commitHook func(ctx context.Context)) func OnRollback(tx Tx, rollbackHook func(ctx context.Context)) But this would mean that both ctx and tx would have to be passed in parameters to all functions called during the body of the transaction. My question is whether putting the transaction in the context using context.WithValue is a reasonable and appropriate use of that mechanism. If not, why not? The use case for this transaction model is not really relevant to the question, but I'll include it for illustrative purposes. Imagine a web server implemented in layers, e.g. transport on top of service on top of database access. One would like to promote the transaction concept out of the database access layer so that multiple calls from the service layer to the database access layer could occur within the same database transaction. One way to do that would be to wrap the service call in an abstract transaction, and have the database layer honor that with database transactions in an encapsulated fashion. Many thanks in advance for your reactions and wisdom. Steve -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
