For fun, some other ways:
Another approach to this is parsing the first few instructions; Go functions have a common prologue, one of which is a jump to a standard epilogue that handles stack growth. The details will vary by architecture and Go version, and there are several flavors of prologues, including some functions with no prologues, but it’ll work for most functions.
Also, on some architectures, gaps between functions are filled with special break/interrupt instructions. In those cases you can probably read forward until you encounter such instructions. (This will be wrong in the rare case in which someone has written an assembly routine containing such an instruction.)
Closures may complicate some of these approaches as well.
-josh