Cgo はかなり遅いです。なぜなら、Go はC 関数を呼び出すために特定の方法でランタイムと呼び出し規則をいじる必要があるからです。それが本当に価値がある唯一の場所は、計算時間がこのコストを大幅に小さくする場合です。並列、分散、GPU などのプログラミングに似ていますが、起動コストはわずかに低くなります。
Go の呼び出し規則を使用するアセンブリを記述でき、それ以外の場合はネイティブの Go コードのように扱われるため、アセンブリの方がはるかに優れていますが、アセンブリは移植性がはるかに低く、読み取りが難しく、メンテナンスがより重くなります。実際、Go 標準ライブラリはPlan 9 スタイルのアセンブリでmath
およびパッケージの一部を記述しています。big
Gonumは、これらの両方の例です。より迅速に実行できる一部の機能には共通のアセンブリを使用しますが、blas および lapack エンジンも活用します。それはGo-blas
実装を提供しますが、C-blas (通常は最終的には Fortran-blas) の方が高速であり、大規模な行列計算の場合、ほとんどの場合、Go を離れるコストが小さくなります。
一般的に、cgo は可能な限り避けたいものです。かなりの計算時間が必要な場合、またはグラフィックスやオーディオ ドライバーなど、純粋な Go で対話するのが自明ではないものと対話する必要がある場合、または OpenCV などの一般的なライブラリにアクセスする必要がある場合にのみ使用してください。それでも、パフォーマンスが本当に気になる場合は、可能であれば、Go 側から複数の呼び出しをスケジュールし、C への単一のコンテキスト スイッチでそれらをすべて一度に実行できる、何らかの「呼び出しプーリング」を実装する価値があるかもしれません。
編集: C++ に関しては、いくつかの重要な問題があります。いくつかの抽象化層なしで特定のライブラリをラップするのは難しい場合があります (cgo は含まれている C++ ヘッダーを適切に処理できないため)。さらに、デストラクタを持つ C++ クラスは実際には値で返すことができず、ヒープに割り当てる必要があります。Go ではリソースの決定論的なファイナライズが許可されていないため、メモリを明示的に解放する関数を提供する必要があり、Go ユーザーはリソースを解放することを覚えておく必要があります。(と呼ばれるドキュメントで読むことができる関数がありますが、runtime.SetFinalizer
誰かがそれを使用しているのを見たことがないとは言えません。ドキュメント自体には多くの注意事項があります)
のような機能defer
はこれをより管理しやすくしますが、最新の C++ プラクティスをより安全にする RAII のような多くのものを台無しにします。