"do while" and "goto out" are different on these area:
1.local variable initialization
void foo(bool t = false)
{
    if (t)
    {
        goto DONE;
    }
    int a = 10; // error : Goto bypass local variable's initialization 
    cout << "a=" << a << "\n";
DONE:
}
It is fine to initialize in-place local variables in do ... while(0) block. 
void bar(bool t = false)
{
    do{
        if (t)
        {
            break; 
        }
        int a = 10;  // fine
        cout << "a=" << a << "\n";
    } while (0);
}
2 difference for Macros. "do while" is a slight better. "goto DONE" in a Macro is so not the case.
If the exit code is more complicated, let see like this:
err = some_func(...);
if (err)
{
    register_err(err, __LINE__, __FUNC__);
#if defined (_DEBUG)
    do_some_debug(err)
#endif
    break;
}
and you write this code again and again, you will probably put them into a Macro.    
#define QUIT_IF(err)                     \
if (err)                                       \
{                                              \
    register_err(err, __LINE__, __FUNC__);     \
    DO_SOME_DEBUG(err)                         \
    break; // awful to put break in macro, but even worse to put "goto DONE" in macro.  \
}
And the code become:
do
{
    initial();
    do 
    {
        err = do_step1();
        QUIT_IF(err);
        err = do_step2();
        QUIT_IF(err);
        err = do_step3();
        QUIT_IF(err);
        ....
    } while (0);
    if (err) {     // harder for "goto DONE" to get here while still using macro.
        err = do_something_else();
    }
    QUIT_IF(err);
    .....
} while (0);
3.do... while(0) handles different levels of exiting with same macro. Code is shown above. goto ... is not the case for Macro cause you need different labels for different levels. 
By saying that, I do not like both of them. I'd prefer to use the exception method. If exception is not allowed, then I use "do ... while(0)", since the whole block is indented, it is actually easier to read than "goto DONE" style.