As pointed out in other answers, in a simple example this does little; its advantages are more obvious when there are many resources to access, and many error conditions. This pseudo code demonstrates this:
boolean allocate_resources (ObjectA **a, ObjectB **b, ObjectC **c) { *a = allocate_a(); if (*a == NULL) { LOG_ERROR("failed to allocate A"); goto fail0; } *b = allocate_b(); if (*b == NULL) { LOG_ERROR("failed to allocate B"); goto fail1; } *c = allocate_c(); if (*c == NULL) { LOG_ERROR("failed to allocate C"); goto fail2; } return true; fail2: release_b(*b); fail1: release_a(*a); fail0: return false; }
Notice how this function works atomically, as seen from the outside - when it returns, either all resources are allocated, or none of them, avoiding leaks.
Compare this with one possible version that uses nesting instead of goto:
This version is much harder to read. The goto version first shows what the main execution path will be; this is not the case here. Nesting makes the code more difficult to read, and also discards horizontal space.
I hope I have not ruined it, and it is functionally equivalent to the first example; I suggest you try to prove to yourself that this is equivalent, and see for yourself how difficult it is to work.
source share