You can feed arbitrary events (keystrokes, mouse clicks, etc.) to the command loop by putting them onto
unread-command-events. For example, the following will cause the command loop to execute a break the next time it is run:
(setq unread-command-events (listify-key-sequence "\C-g"))
Note that this only feeds events to the command loop, so it will do nothing interesting if you're looping in your own code.
A different approach, which you seem to be aware of, is to find the function a given key is bound to, and execute it yourself:
(funcall (global-key-binding "\C-g"))
This will execute the command immediately. Beware, however, that some commands have different behaviour depending on whether they are called interactively, such as defaulting arguments. You'll want to compensate for that by using
(call-interactively (global-key-binding "\C-g"))