go はインタプリタ型言語です。 Go (Golang とも呼ばれます) は、Google によって開発された、静的に強く型付けされ、コンパイルされ、ガベージ コレクション機能を備えた同時プログラミング言語です。 Go 言語の利点: 習得が容易、開発と運用の高い効率、強力な標準ライブラリ、言語レベルで定義されたソース コードのフォーマットなど。
このチュートリアルの動作環境: Windows10 システム、GO 1.18、thinkpad t480 コンピューター。
Go (Golang とも呼ばれる) は、Google の Robert Griesemer、Rob Pike、Ken Thompson によって開発された、静的に強く型付けされたコンパイル言語です。
Go の構文は C 言語に似ていますが、変数の宣言が異なります。 Go はガベージ コレクションをサポートしています。 Go の並列モデルは Tony Hall の Communicating Sequential Process (CSP) に基づいており、同様のモデルを採用する言語には Occam や Limbo などもありますが、チャネル送信などの Pi 演算の機能も備えています。プラグインのサポートはバージョン 1.8 でオープンされ、一部の関数を Go から動的にロードできるようになりました。
C と比較すると、Go には列挙、例外処理、継承、ジェネリックス、アサーション、仮想関数などの関数が含まれていませんが、スライス タイプ、同時実行性、パイプ、ガベージ コレクション、言語レベルが追加されています。インターフェイスなどの機能のサポート。 Go 2.0 バージョンはジェネリックスをサポートしますが、アサーションの存在に対して否定的な態度をとっており、型継承は提供していないとも主張しています。
Java とは異なり、Go には文字列型と同様に、連想配列 (ハッシュ テーブル (Hash) または辞書 (Dictionaries) とも呼ばれます) が組み込まれています。
Go 言語の利点
Go は習得が簡単です
これは真実です:プログラミング言語の知識がある場合は、「Go Language Journey」を数時間学習することで Go の構文のほとんどをマスターし、数日で最初の実際のプログラムを作成できます。実践的な Go プログラミングを読んで理解し、パッケージのドキュメントを参照し、Gorilla や Go Kit などの Web ツールキットを操作すれば、かなり優れた Go 開発者になれるでしょう。
これは、Go の主な目標がシンプルさであるためです。 Go を学習し始めたとき、Java を初めて発見したときのことを思い出しました。それは、シンプルな言語と豊富だが肥大化していない標準ライブラリです。現在の Java 中心の環境と比較すると、Go を学ぶのは新鮮な経験です。 Go の単純さにより、Go プログラムは非常に読みやすいですが、エラー処理には若干の頭の痛い問題が追加されます (これについては以下で詳しく説明します)。
Go 言語の単純さは間違いである可能性があります。ロブ・パイクの言葉を借りれば、「シンプルさは同時に複雑であり、シンプルさの背後には多くの罠が私たちを待っていることがわかります。ミニマリズムは私たちを DRY (Don'trepeat Yourself) 原則に違反させます。」
ゴルーチンとチャネルに基づくシンプルな同時プログラミング
ゴルーチンはおそらく Go の最も優れた機能です。これらは軽量のコンピューティング スレッドであり、オペレーティング システムのスレッドとは異なります。
Go プログラムが I/O をブロックしていると思われる操作を実行すると、Go ランタイムは実際にはゴルーチンを一時停止し、結果が利用可能であることをイベントが示すとゴルーチンを再開します。その間、他のゴルーチンの実行がスケジュールされています。したがって、同期プログラミング モデルでは、非同期プログラミングのスケーラビリティの利点が得られます。
Goroutine は軽量でもあります。Goroutine のスタックは需要に応じて拡大または縮小します。つまり、数百、さらには数千の Goroutine があっても問題ありません。
私の古いアプリケーションには goroutine の脆弱性がありました。これらの goroutine は終了する前にチャネルが閉じるのを待っていましたが、チャネルは決して閉じられませんでした (一般的なデッドロックの問題)。このプロセスは理由もなく CPU の 90% を消費し、expvars をチェックすると 600k のアイドル状態の goroutine が表示されます! goroutine スケジューラが CPU を独占しているのだと思います。
もちろん、Akka のようなアクター システムは、何百万ものアクターを簡単に処理できます。その理由の 1 つは、アクターにはスタックがないことが挙げられますが、大規模な同時リクエスト/応答アプリケーション (つまり、 http API)。
チャネルはゴルーチンが通信する方法です。チャネルは、脆弱な低レベルの同期プリミティブに依存することなく、ゴルーチン間でデータを送受信するための便利なプログラミング モデルを提供します。チャネルには独自の使用パターンのセットがあります。
ただし、チャネルのサイズが不適切であると (デフォルトではバッファリングされない)、デッドロックが発生する可能性があるため、チャネルについては慎重に検討する必要があります。また、チャネルには不変性がないため、チャネルを使用しても競合状態が防止されないことも以下で説明します。
豊富な標準ライブラリ
Go の標準ライブラリは非常に豊富で、特にネットワーク プロトコルや API 開発に関連するすべてのもの (http クライアントとサーバー、暗号化、アーカイブ形式、圧縮) が充実しています。 、メールの送信など。テキストと HTML を生成する HTML パーサーとかなり強力なテンプレート エンジンもあり、XSS 攻撃 (Hugo で使用されるものなど) を自動的に除外します。
さまざまな API は一般にシンプルで理解しやすいです。これらは、単純すぎるように見えることがあります。これは、ゴルーチン プログラミング モデルが、「一見同期しているように見える」操作のみを考慮すればよいことを意味していることが 1 つ理由です。これは、時間の計算について最近知ったように、いくつかの一般的な関数が多くの特殊な関数を置き換えることができるためでもあります。
Go は優れたパフォーマンスを備えています
Go はローカルの実行可能ファイルにコンパイルされます。 Go ユーザーの多くは Python、Ruby、または Node.js から来ています。彼らにとって、これはサーバーが処理できる同時リクエストの数が大幅に増加することを意味するエキサイティングな経験です。これは、同時実行ではないインタープリタ言語 (Node.js) またはグローバル インタープリタ ロックが設定されているインタープリタ言語を使用している場合には、実際にはごく普通のことです。言語の単純さと組み合わせると、これが Go がエキサイティングな理由の説明になります。
ただし、Java と比較すると、生のパフォーマンス ベンチマークでは、状況はそれほど明確ではありません。 Go が Java に勝るのは、メモリ使用量とガベージ コレクションです。
Go のガベージ コレクターは、レイテンシーを優先し、サーバーで特に重要なダウンタイムを回避するように設計されています。これにより CPU コストが高くなる可能性がありますが、水平方向にスケーラブルなアーキテクチャでは、マシンを追加することで簡単に解決できます。 Go は Google によって設計されており、リソースが不足することはありません。
Java と比較すると、Go のガベージ コレクター (GC) はやることは少ないです。スライスは連続した配列構造であり、Java のようなポインターの配列ではありません。同様に、Go マップも同じ目的を達成するために小さな配列をバケットとして使用します。これは、ガベージ コレクターの作業が減り、CPU キャッシュのローカライゼーションが向上することを意味します。
Go には、コマンド ライン ユーティリティにおいて Java よりも優れた点もあります。ネイティブの実行可能ファイルとして、Go プログラムには起動時のオーバーヘッドがありませんが、Java では最初にバイトコードをロードしてコンパイルする必要があります。
ソース コード形式の言語レベルの定義
私のキャリアの中で最も白熱した議論のいくつかは、チームのコード形式の定義をめぐって起こりました。 Go は、コードの正規形式を定義することでこの問題を解決します。 gofmt ツールはコードを再フォーマットしますが、オプションはありません。
好むと好まざるにかかわらず、gofmt はコードのフォーマット方法を定義し、この問題を完全に解決します。
標準化されたテスト フレームワーク
Go は、標準ライブラリで優れたテスト フレームワークを提供します。並列テスト、ベンチマークをサポートし、ネットワーク クライアントとサーバーを簡単にテストするための多くのユーティリティが含まれています。
Go プログラムは操作が簡単です。
Python、Ruby、Node.js と比較して、単一の実行ファイルをインストールする必要があることは、運用保守エンジニアにとって夢のようなことです。 Docker の使用が増えるにつれて、この問題は少なくなりますが、スタンドアロンの実行可能ファイルは、小さい Docker イメージも意味します。
Go にはいくつかの可観測性機能も組み込まれており、expvar パッケージを使用して内部ステータスとメトリクスを公開したり、新しいコンテンツを簡単に追加したりできます。ただし、これらはデフォルトの http リクエスト ハンドラーで自動的に公開され、保護されないので注意してください。 Java には JMX に似たものがありますが、より複雑です。
クリーンアップの忘れを防ぐためのdeferステートメント
deferステートメントの目的はJavaのfinallyと似ています。つまり、現在の関数の最後にクリーンアップコードを実行します。この関数がどのように終了するかに関係なく。 defer の興味深い点は、コード ブロックとは関係がなく、いつでも表示できることです。これにより、クリーンアップ コードはクリーンアップが必要なコードにできるだけ近くなります:
file, err := os.Open(fileName) if err != nil { return } defer file.Close() // 用文件资源的时候,我们再也不需要考虑何时关闭它
もちろん、Java の試用版リソースは冗長ではなく、所有者が削除されると Rust が自動的にリソースを宣言します。 Go ではリソースのクリーンアップについて明示的に把握する必要があるため、リソースの割り当てに近い状態で行うことが望ましいです。
新しい型
イライラしたり怖がらせたりするものがいくつかあるので、型が好きです。たとえば、永続的なオブジェクト識別子をどこでも文字列型またはlong型として扱います。使用。通常、パラメータ名の ID の型をエンコードしますが、関数にパラメータとして複数の識別子があり、一部の呼び出しがパラメータの順序と一致しない場合、微妙なバグが発生します。
Go は、新しい型に対する第一級のサポートを備えています。つまり、その型は既存の型であり、元の型とは異なる独立した ID が与えられます。パッケージ化とは対照的に、新しい型には実行時のオーバーヘッドがありません。これにより、コンパイラはこの種のエラーをキャッチできるようになります:
type UserId string // <-- new type type ProductId string func AddProduct(userId UserId, productId ProductId) {} func main() { userId := UserId("some-user-id") productId := ProductId("some-product-id") // 正确的顺序: 没有问题 AddProduct(userId, productId) // 错误的顺序:将会编译错误 AddProduct(productId, userId) // 编译错误: // AddProduct 不能用 productId(type ProductId) 作为 type UserId的参数 // Addproduct 不能用 userId(type UserId) 作为type ProfuctId 的参数 }
残念ながら、ジェネリックスがないため、新しい型の操作が面倒になります。再利用可能なコードを記述するには、プリミティブ型から値を変換する必要があるからです。
プログラミング関連の知識について詳しくは、プログラミング ビデオをご覧ください。 !
以上がgo はインタプリタ型言語ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。