Personally I think
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer std.debug.assert(gpa.deinit() == .ok);
const allocator = gpa.allocator();
// ...
should basically be your default unless you know you need (or can use) something else. The GPA will catch bugs for you in modes with safety enabled, and it is the most future-proof since once implement a fast general purpose allocator · Issue #12484 · ziglang/zig · GitHub is addressed it will be a good choice for release modes, too (this is also why I think the GPA should be used in example code).
Note, though, that for Zig code that conforms with the ‘pass an allocator for anything that needs to allocate’ convention, in my experience it’s basically never necessary to choose an allocator beyond main
(except for the odd ArenaAllocator
wrapping a passed in allocator here and there). And when writing a library, you basically don’t have to worry about choosing an allocator at all–that’s for the user of your library to decide.