In Go, you would use additional bits to identify whether the zero value is valid/present. You would not use the zero value of an integer, or other type, alone, unless the zero value truly has special meaning and can stand on its own; an uncommon case for integers, as you point out.
Unfortunately, there is no escaping the extra bits. Not a terribly big deal for a large, powerful machine with lots of memory, but might be a big deal over constrained networks. Presumably that is why proto3 tried to save on the amount of data being transferred. It adds up at Google scale. But it did eventually walk back on that idea, making the extra data opt-in.