One possible solution is to use a bits of the protoreflect library for Go that I've written:
When parsing, you'll want to use the flag to include source code info. This will preserve a little more comment info than descriptor produced by protoc. FWIW, the descriptor with source info can be had from protoc with an invocation like so:
protoc -o outputfile --include_source_info --include_imports some.proto
Once the files are parsed, you can easily recursively visit all of the fields and modify the field descriptors to add a default value.
The main downside is that this in no way preserves formatting from the original file. The formatting produced isn't bad, but it doesn't quite look like hand-written code due to the extra whitespace you'll see (blank line between every element). To preserve formatting, you probably will need to write a custom parser.