クイック検索

FAQ

Goの起源

このプロジェクトの目的は何ですか?

ここ10年以上の間、メジャーなシステム言語と呼ばれるものは登場していません。しかし、この間コンピュータをめぐる景色は大きく変化しています。この変化には以下のような傾向があります:

  • コンピュータはとてつもなく速くなりましたがが、ソフトウェア開発は速くなっていません。
  • 依存関係の管理というものが、今日のソフトウェア開発において、大きな位置を占めていますが、C言語の伝統のヘッダファイルはクリーンな依存性分析と高速なコンパイルとは対極です。
  • JavaやC++のような扱いにくい型システムに対する反乱が徐々に拡大しつつあります。PythonやJavaScriptのような、動的な型を持つ言語に対して、人々が押し寄せてきています。
  • 人気のあるシステム言語の中には、ガーベジコレクションや並列計算のような基本概念をサポートしていないものがあります。
  • マルチコアのコンピュータの出現によって、人々の間に、不安と混乱が発生しました。

私たちは、並列をサポートし、ガベージコレクションを備えた、コンパイルの速い言語に挑戦することは価値があることだと信じています。上記の点に関して:

  • 大きなGoのプログラムを一台のコンピュータで数秒で数秒以内にコンパイルすることが可能です。
  • Goは、依存性の分析を簡単にし、C言語スタイルのインクルードファイルや、ライブラリの持つオーバーヘッドのほとんどを解消するようなソフトウェアの構成が行えるモデルを提供します。
  • Goの型システムには階層構造がないため、型同士の関係を定義するに貴重な時間を使う必要はありません。また、Goは静的な型システムを持つ言語ですが、典型的なオブジェクト指向言語と比べると型を作成するのが気軽に行えるような言語になっています。
  • Goは完全なガーベジコレクションを備え、言語レベルで並列実行とコミュニケーションの機能をサポートしています。
  • これらのデザインにより、Goはマルチコアのマシン上で動作する、システムソフトウェアの構築を行える様々な機能を提供しています。

名前の由来は?

“Ogle”というのはGoのデバッガーの名前としていい名前になると思います。

6gというのは何を指す名前ですか?

6g(と、8g, 5g)というのは伝統的なPlan 9のC言語のコンパイラの名前です。詳しい説明は http://plan9.bell-labs.com/sys/doc/compiler.html のSection 2の表を参照してください。6というのはアーキテクチャを表す文字で、AMD64(あるいはx86-64という呼び方が好きな人もいるでしょう)を表します。gはGoを表しています。

C++のライブラリとコミュニケーションを行うために、なぜライブラリを書く必要があるのですか?

私たちもこのことについて考えました。ですが、ガーベジコレクションが無い、依存性のチェーンが異様に長い、ネストされたインクルード、並列実行のサポートがないなど、C/C++の言語設計そのものに起因する多くの問題があります。C/C++をサポートするには、もっと根本からアプローチしていかなければ実現可能な解は得られないだろう、と考えています。

なぜGoはWindows上で実行できないのですか?

私たちも、世界中のコンピュータのうちのWindowsが走っているものが大多数を占めていて、それらのコンピュータの上でGoのプログラムが動けばどれだけすばらしいことだろう、と思います。しかし、Goのチームは小さいために、Windowsに今すぐ移植を行うリソースがありません。ただ、もしもWindows版の開発をしたいと考えている人がいるのであれば、質問に答えたりアドバイスをしたりというのは積極的に行っていきたいと思っています。

ノート

訳注) Windowsに限らず、 様々な環境への移植 が行われています。

マスコットの由来は何ですか?

マスコットとロゴはPlan 9 bunnyとして知られる Glenda をデザインした Renée French によるものです。gopherは何年か前に WFMU Tシャツに使用されていたものから派生しました。ロゴとマスコットには Creative Commons Attribution 3.0 ライセンスが適用されています。

扱い方

だれが言語を使うのですか?

Go は、実験中です。 我々は、冒険心があり、いろいろと試し楽しめる人を望んでいます。 すべてのプログラマではないです、しかし我々は十分にさらなる発展を正当化するため提供しているアプローチで満足感を得ることを望んでいます。

Google内部でGoを使うのですか?

Go プロジェクトでは、Google 内部で、簡単にいろいろな種類のサーバーや他のGoogle ソフトウェアを記述するように考案されています。 しかし、まだ大規模なプロダクトで使用するために、十分に成熟してはいません。 一方で、我々はまたサーバ環境としての候補として、Goを使って、実験を続け開発をしています。 もう一息というところです。 例えば、http://golang.org/ の背後にあるサーバーは、Goでできています。 それはちょうどgodocドキュメントサーバーが動作しているという事実です。

Go は、C/C++プログラムとリンクできますか?

2つのGoコンパイラの実装では、”6g”他がり、一般的にGCかgccgoが呼ばれています。 GCを使用すると、別の呼び出し規約とリンカのため、唯一のCプログラムとリンクすることができます。 これは、Cコンパイラであって、C++コンパイラではありません。 Gccgo は、GCCのフロントエンドとして使うことができ、GCCでコンパイルされた、C/C++プログラムとリンクすることができます。 Go は、ガベージコレクションをするため、単純にリンクさせることは、賢明ではありません。

“外部関数インターフェイス”は、Goのコードから安全に、”C”で書かれたライブラリを呼び出すことができます。 我々は、SWIGを使って、C++ライブラリが利用できるようになることを期待しています。 C/C++からGoコードを安全に呼び出す方法はまだありません。

Go は、Googleの”protocol buffers”をサポートしますか?

Protocol buffers は、サポートします。 我々の計画では、次のリリースに、”protocol buffer”のライブラリとジェネレータを取り込みます。 データリフレクションを使っていますので処理時間は遅いです。しかし、新しい実装を計画しています。

Goのホームページを他の言語に翻訳してもいいですか?

もちろんです。私たちは開発者たちにGo言語のサイトを彼ら自身の言語に翻訳することを推奨しています。しかし、Googleのロゴあるいはブランド(golang.orgには出てきません)をあなたのサイトに追加する場合、 http://www.google.com/permissions/guidelines.html にあるガイドラインを遵守する必要があるでしょう。

設計

なぜGoにはXという機能がないのですか?

どんな言語であっても、目新しい機能が含まれている反面、誰かが好きな機能を省略することがありえます。Goはプログラミングの喜び、コンパイル速度、概念の直交性、並列実行やガーベジコレクション機能のサポートに重点をおいてデザインされています。みなさんの好きな機能がないとすれば、それはコンパイル速度や明確な設計などとマッチしないか、基本的なシステムのモデルを複雑にしてしまうから、という理由からだと思います。

もしもGoに機能Xがないために苦労を強いられているのであれば、私たちに恨みを向けないで、Goが持っている機能を調べてみてください。もしかしたらXの機能が欠けている部分が、面白い方法で補完されているの、というのを見つけることができるかもしれません。

なぜ文法はC++と異なっているのですか?

この質問や、言語設計に関するその他の質問に関しては、 言語設計FAQ にて回答します。

オブジェクト指向プログラミング

Goはオブジェクト指向言語ですか?

イエスとも言えますし、ノーとも言えます。Goは型もメソッドもあり、オブジェクト指向のスタイルのプログラミングを行うことができますが、型には階層はありません。Goでは”インタフェース”という概念が提供されていて、今までとは異なるアプローチを行うことができます。私たちは簡単に使えると信じていますし、いくつかの方法の中ではより汎用的だと思っています。また、他の型に対して、型を埋め込んで類似のモノを提供するということもできますが、サブクラスとは異なります。そのうえ、GoメソッドはC++かJavaよりも汎用的です。構造体だけでなく、あらゆる種類のデータに対して定義することができます。

また、型の階層がないということは、Goの”オブジェクト”はC++やJavaなどの他の言語よりも軽量である感覚を与えます。

どのようにすれば動的ディスパッチが行えますか?

メソッドのダイナミックディスパッチを行う唯一の方法は、インタフェースを通じて呼び出す方法になります。構造体やその他の型に定義されたメソッドは、常に静的に解決されます。

並列プログラミング

アトミックな操作というのはどれでしょうか?ミューテックスはどうなっているんでしょうか?

私たちは、まだそれを完璧には定義していませんが、アトミックという状態に関する詳細情報は、Goのメモリモデルの定義の中で読むことができます。また、並列に関する質問に関しての詳細については、言語設計のFAQの中で説明しています。

ミューテックスに関しては、syncパッケージで実装されていますが、多くのプログラマが、より高級なテクニックにトライしようとすることを願っています。一度に一つのgoroutineだけが特定のデータに関する責任を持つようにプログラムする、という構造にすることを考えてください。

共有メモリを使ったコミュニケーションはしなようにしてください。代わりに、コミュニケーションを利用した共有メモリを使用してください。

コードの記述

ライブラリのドキュメントはどのように記述されますか?

Goにはソース中からドキュメントの部分のみを抽出するgodocという機能があります。これはコマンドラインやWeb上で使用することができます。 http://golang.org/pkg/ はその一例です。実は http://golang.org/ 全体がgodocで実装されています。

Goのプログラミングスタイルガイドはありますか?

結論から言うと、命名やレイアウト、ファイルの構成といった最小限のルールしか存在しないでしょう。 Effective Goのドキュメントにも、いくつかコーディングスタイルの参考になるものがあります。もっと直接的には、gofmtがレイアウトのルールを強制するpretty-printerになっています。gofmtはソースを、構文として許された妥当な要約(すべきもの、せざるべきもの)に置換します。リポジトリ内のすべてのGoのコードは、gofmtを通してあります。

Goのライブラリにパッチを当てるにはどうすればいいですか?

ライブラリのソースはgo/src/pkgにあります。もし重要な変更をしたければ、着手する前にメーリングリストで議論するようにしてください。

Goプロジェクトに貢献するために、どのな手順で進めたら良いかについてのより詳しく書かれたドキュメントがあるので、それを見てください。

複数ファイルからなるパッケージを構成するにはどうすればいいですか?

ディレクトリにパーケージ化したい全てのソースファイルをまとれば、ソースファイルは必要に応じて他のファイルのアイテムを参照出来ます。ヘッダーの定義や事前の宣言等は必要ありません。

また、複数ファイルからなるパーケージも、単一ファイルのようにコンパイルやテストをすることができます。

ユニットテストはどのように記述しますか?

パッケージのディレクトリ内に_test.goで終わるファイルを新規作成してください。ファイル内で”testing”モジュールをインポートし以下のような関数を定義します。

func TestFoo(t *testing.T) {
    ...
}

ディレクトリ内でgotestを実行します。スクリプトはテスト関数を見つけるとテストバイナリをビルドし、テストを実行します。

アサーション機能は無いのですか?

Goはアサーション機能を提供しません。アサーションが便利なのは否定できませんが、我々の経験上プログラマは、それを適切なエラー処理とエラー出力を避けるために使っています。適切なエラー処理とは、サーバがクラッシュする代わりに致命的ではないエラーを発生するにとどめ、処理を続けられるということを意味しています。適切なエラー出力は、エラーが直接的や部分的だったとき、クラッシュ時の膨大なトレースを翻訳する作業からプログラマを開放することを意味します。正確なエラー出力は、エラーを見つけたプログラマーがそのコードに精通していない時ほど重要です。

同じことが、テストプログラムにassert()を使った時にも言えます。適切なエラー処理は、例えば、あるテストが失敗しても、そこで停止せず次のテストも続けて実行することができるということを意味しています。そうすることで、あるバグを直そうとしたとき、全体として何がおかしいのかを把握することができるからです。例えば、isPrimeという素数判定をテストするとき、2,3,5,7(もしくは2,4,8,16)という入力に対し、2という数字で誤った答えを返してそこでテストが停止してしまうよりも、誤った答えを返しながらもテストを続行し、全ての数字を評価する方が、原因を探る上で都合が良いでしょう。テストを実行してバグを出したプログラマがそのコードに精通しているとは限りません。今良質のエラーメッセージを記述するために費やした時間は、後にテストが失敗したときに報われるでしょう。

テストで、もし良いエラーを書くために何度も何度も大量に余分なコードをかく必要があるように見えても、それは良い机上テストの代わりになる可能性があります。Goはデータ構造のリテラルに対するすばらしいサポートを備えています。

Goの言語使用やライブラリには、最近の言語の慣習に反する部分があることは理解しています。それは、単純に私たちがそれらの慣習とは違ったアプローチを試してみる価値があると考えたからなのです。

実装

コンパイラを構築するために、どのようなコンパイラ技術を使用してますか?

Gccgo は、 C++ フロントエンドとなり、再帰パーサーにより、標準のGCCのバックエンドを利用できます。

Gc は、C から yacc/bision をパーサとして利用し書かれています。

しかし、Gc は新しいプログラムです。 それは Plan 9 の Cコンパイラ(http://plan9.bell-labs.com/sys/doc/compiler.html)に適しており、そして Plan 9 ローダとは異なるELFバイナリを使用します。

我々は、6gを書く上で、オリジナルの Go コンパイラに関して熟考しました。Go そのものではなく、ブーストラップの難しさとオープンソースでの配布、特にGo環境をセットアップをする上で、Goコンパイラは必要であるためです。

Gccgo は後から出ました。 これは熟考して書かれた Go に適したコンパイラです。 Go は、優れた言語で、コンパイラのための実装があります。Go ネイティブのレクサーとパーサはすでに用意してあり、 /pkg/go から使えます。

我々は、6g で LLVM を使うことを熟考しました。 しかし、LLVMではとても大きく遅かったため、パフォーマンス目標を満たせないと感じました。

どのようなランタイム実装ですか?

今回も問題の独立のために、ランタイムは、C言語と少しのアセンブラです。とはいえ、 Go は、今ではほとんどの実装が可能です。

Googo ランタイムは、glibcを使っています。 Gc は、カスタムライブラリを使っており、変更履歴を管理しています。

Plan 9 Cコンパイラとコンパイルしたものは、セグメントスタックのgoroutinesをサポートします。 Gccgo にスタック管理機能を提供するために進行中です。