これに対する最大の動機と最大の結果は、コンパイル時間の改善だと思います。テクニカル プレビュー ビデオでは、短期間に大量のコードをコンパイルする能力が強調されていました (彼らの例では、MacBook で 8 秒で 200,000 行のコードをコンパイルしました。マシンの仕様は示されていません)。
また、技術ビデオでは、彼らが達成した最大の方法の 1 つは、モジュールのコンパイルとリンクの方法を変更したことであると具体的に述べています。
現在の C/C++ システムで何かがどのように機能するかの例を次に示します。
クラス A はヘッダー ファイル C_H で定義され、C_CPP で実装されます。クラス B は C から派生し、ファイル B_H および B_CPP に実装されています。クラス A は B から派生し、ファイル A_H および A_CPP に実装されます。
派生チェーンのため、A_CPP には A_H、B_H、および C_H が含まれます。B_CPP には、B_H と C_H が含まれます。C_CPP には C_H が含まれます。基本的に #include をカット アンド ペースト操作に変える C プリプロセッサの性質により、C_H の内容はコンパイラで 3 回実行され、B_H は 2 回実行されます。
さらに、A_CPP、B_CPP、および C_CPP の内容はすべて、独自のオブジェクト ファイルに存在します。したがって、リンカが Ao を解決しようとすると、Bo と Co の両方をロードして処理する必要があります。また、Bo を解決するときは、Co を再度処理する必要があります。
プリコンパイル済みヘッダーは、この問題の最初の部分でかなり役立ちますが、維持するのが大変な場合もあり、その理由で単純にヘッダーを使用しない多くの開発者を知っています。また、問題が根本的に変わるわけではありません。ヘッダーは複数のレベルで複数回処理されますが、ソースの代わりにプリコンパイルされたバイナリが処理されるだけです。いくつかのステップが切り取られていますが、プロセス全体ではありません。
Go は異なる方法でアプローチします。彼らのテクニカルトークからのPDFからの直接の言葉で:
「Go コンパイラは、オブジェクト ファイルから推移的な依存関係の型情報を取得しますが、必要なものだけを取得します。A.go が B.go に依存している場合、C.go に依存している場合: - C.go、B.go、次に A.go をコンパイルします。 - A.go をコンパイルするために、コンパイラは Co ではなく Bo を読み取ります。大規模な場合、これは大幅なスピードアップになる可能性があります。"
OK、わずかな接線が完了しました。なぜそれが関連するのですか?答えは、Go Tech Talk PDF にもあります。
「パッケージ モデル: 高速なビルドを可能にする明示的な依存関係。」
Go 開発者は、非常に大規模なプロジェクトであっても、コンパイル時間が秒単位で測定される場合、開発者が維持する方が生産的であるというスタンスをとったと推測しています。短いコンパイル時間。200,000 行のコードをコンパイルし、無関係なパッケージのインポートがあることを発見するのに 8 秒かかり、それを見つけて修正するのに (優れた IDE または開発環境に精通している場合) 5 ~ 10 秒かかるとします。再コンパイルするのにさらに 8 秒かかります。これを合計 30 秒と呼びます。これで、今後のコンパイルはすべて 10 秒の範囲内にとどまります。または、不要な依存関係を含めてモジュールを成長させ、コンパイル時間が 8 秒から 10 秒、12 秒、または 15 秒に増加するのを監視することもできます。私たちは皆、時間を分単位でコンパイルすることに慣れているので、大したことではないように思えますが、それが 25% のパフォーマンス低下であることに気付き始めると、立ち止まって少し考えてみてください。
Go のコンパイル時間はすでに超高速です。また、プロセッサの速度は (以前ほどではないとしても) 依然として向上しており、利用可能なコアの数も増加していることも考慮してください (また、大量のコードをコンパイルすることはマルチスレッドに適しています)。今日、200,000 行のコードが 8 秒で処理されるということは、10 年後に 200,000 行のコードが実質的に瞬時にコンパイルされることを想像しても不合理ではないことを意味します。Go チームはここでコンパイル時間を過去のものにするという意識的な決定を下したと思います。あなたが提起した問題はそのほんの一部にすぎませんが、それはまだその一部です。
まったく別のことですが、Go チームは、優れたプログラミング プラクティスを強制する言語設計の哲学も開発したようです。彼らの名誉のために、彼らは深刻なパフォーマンスの低下なしにそれを達成するために努力し、大部分は成功しました。[余談: 実際にパフォーマンスに影響を与えていると思いつくのは、ガベージ コレクションと強制的に初期化された変数の 2 つだけです。後者は、この時代ではかなり些細なことです。] . これはプログラミングの世界では古くからある議論であり、Go が好きか嫌いか、どちら側に傾倒したかは明らかです。
2 つの力が一緒になって彼らの決定に影響を与えたと思います。結局のところ、これは良い方法だと思いますが、「--strict」フラグなどを使用してこれを行うことを許可することを提案した他のコメンターを支持しますが、特にプロジェクトのライフサイクルの初期段階では、特定の動作はオプションです。後で必要になることがわかっているコードを最初に書き始めたとき、それらを必要とするコードをまだ書いていなくても、変数を定義したり、パッケージを含めたりしている自分を簡単に見ることができます。