The authors of the encoding/json library thought the same. As a way to exit from deep down in a parse stack it works well especially if you only have limited entry points.
https://cs.opensource.google/go/go/+/refs/tags/go1.19:src/en...
uses well typed panics.
The stdlib is not always the best example of idiomatic Go; encoding/json is particularly infamous for having poor performance and awkward APIs. I'm fairly confident that it it was re-written today, it wouldn't use panic/recover.
which was why I used it. I basically had a single entry point (if i remember correctly) something like "match(regex, text)" and hence it made it easier for me to write by just panic at the error location and recover within the match() call than putting if err != null everywhere. Or at least that's what I thought then in terms of cleanliness.
in all the production code I've written in go since then, I haven't used panic/recover because its not considered proper. But I'm still a bit skeptical as do think it can make code a bit cleaner when writing a library (I'd 100% agree though that the panic should never escape the library though and only a plain error returned to the caller, i.e. need strong library boundaries for this).