A WooCommerce product is a post, so get_post() returns something usable and the price is right there in the meta. It is also wrong for variable products, where the meta on the parent is not the price a customer pays.
$product = wc_get_product( $post_id );
$product->get_price(); // resolves variations and sale prices
$product->is_in_stock();
$product->get_price_html(); // formatted, with the range for variables
if ( $product->is_type( 'variable' ) ) {
$children = $product->get_children();
}
wc_get_product() returns the right class for the product type, so the same call handles simple, variable, grouped and external products without a switch. Reading _price from post meta directly skips all of that, and also skips the filters other extensions use to apply role-based or dynamic pricing — which is how a discount plugin ends up working everywhere except your custom template.