Go (プログラミング言語)
Goはプログラミング言語の1つである。2009年、GoogleでRobert Griesemer、ロブ・パイク、ケン・トンプソンによって設計された。Goは、静的型付け、C言語の伝統に則ったコンパイル言語、、ガベージコレクション、、CSPスタイルの並行性などの特徴を持つ。Goのコンパイラ、ツール、およびソースコードは、すべてフリーかつオープンソースである。
また、軽量スレッディングのための機能、のような動的型付け言語のようなプログラミングの容易性、などの特徴もある。処理系としてはコンパイラのみが開発されている。マスコット・キャラクターはGopher（ホリネズミ）。
発表当初はLinuxとMac OS Xのみしかサポートしていなかったが、2012年3月にリリースされたバージョン1.0からはもサポートされている。2014年12月にリリースされたバージョン1.4からAndroidをサポートし、2015年8月19日にリリースされたバージョン1.5からiOSをサポートしている。また、2011年5月10日に公開された 1.5.0 でも、言語がサポートされている。2018年8月にリリースされたバージョン1.11からWebAssemblyをサポートした。
しばしばGolangやGo言語と表記されることがあるが、言語の正式名称はGoである。golangという通称は、公式サイトのドメインである"golang.org"に由来するものである。このドメインになったのは"go.org"が取得できなかったからであるとされている。
また、公式のロゴではすべて大文字で"GO"と描かれているが、言語の名前としてはGoであるとされている。
2009年11月にGoが初めて発表され、バージョン1.0が2012年3月28日にリリースされた。GoはGoogleの本番システムの一部で使用されており、他の多数の企業やオープンソースプロジェクトでも使用されている。
主に次の2つの実装が存在する。Goの起源はGoogleのエンジニアであるRobert Griesemer、ロブ・パイク、ケン・トンプソンによる、新しいプログラミング言語を設計する実験的なプロジェクトに端を発する。他の言語がよく受ける批判を解決するとともに、それらの言語のよい特徴をできる限り損なわないようにすることを目指した。彼ら設計者たちは、新しい言語として、以下の特徴を持つものを構想していた。後のインタビューで、3人の言語設計者すべてが、新しい言語を設計する主なモチベーションとしてを共有していたことを述べている。
バージョン1.6から、64ビットMIPS上で動作するLinux版および32ビットx86上で動作するAndroid版ポートが追加された。
2017年7月13日、バージョン2への取り組みへの開始が発表された。バージョン1.x系とバージョン2の開発は並行して行われ、バージョン1.20がバージョン2と同義となると宣言されている。
2018年4月、旧ロゴ（Gopherマスコット）がテキストと3本の直線からなる新しいデザインのものに変更された。しかし、マスコットはそのまま変わっていない。
次のコードはGoで書いたHello worldプログラムである。
package main
import "fmt"
func main() {
次のサンプルプログラムは、Goの並行性機能をデモンストレーションする非同期プログラムの実装である。2つの"goルーチン"（軽量スレッド）を立ち上げている。一方はユーザーがテキストを入力するのを待機し、他方はタイムアウトを実現する。文が2つのgoルーチンがメインルーチンにメッセージを送信するのを待機し、最初に到達したメッセージに対して動作を実行する（コード例はDavid Chisnallの本のコードを一部修正している）。
package main
import (
func readword(ch chan string) {
func timeout(t chan bool) {
func main() {
構文は様々な言語に部分的に類似している。変数などにおける型の記法はLimboから引き継いだものと思われる、型名を後置するもので、PascalやAdaに類似している。ブロックの区切りに波括弧を使う記法はC言語他多くと同様である。for文やif文では、条件式を丸括弧で括らず、帰結部分には波括弧が必須である。他に、並列処理について、CSPを参考としている、チャネルによるスレッド間通信機能の構文がある。
Goには構造体という概念があり、実装は下記の様に記述する。
コード例から分かる通り、構造体には型名、フィールド、メソッドが定義されている。GoにはJavaのような言語が持つクラスやオブジェクトのような概念は無いが実質的には構造体はそれらに近い役割を提供する。
では、関数にcodice_1のようなレシーバーの宣言を追加してメソッドを定義する。レシーバーの宣言は codice_2 と記述する。レシーバー内の変数名は自由に指定が可能であり、受け取り方は値渡し、ポインター渡しの2種類から指定出来る。
型とメソッドが切り離されており、型は一切メソッドに依存しない。メソッドと型は、メソッドの追加対象となる型名をレシーバーの型名に指定することで関連付けるようになっている。メソッドは型から切り離されているため型本体を変更する事なくメソッドを追加することが可能であり、同一パッケージ内限定ではあるが、開放された型を実現している。
には型を初期化したり終了処理する機能が存在しない。初期化は型に所属しない関数や、他の型のメソッドで行うようになっている。
ではC++のtypedefのように新しい型を定義できる。
次の例では、codice_3型を元に codice_4 という新しい型を定義している。
これは単に既存の型に別名を与えているのではなく元のcodice_3型と別の型を定義している点が大きく異なる。
新しく定義した型であれば、元の型が構造体型でなくともメソッドを追加することが出来る。例えばcodice_3型やマップ型といった事前定義済み型(組み込み型)に対してもメソッドを追加することが可能である。
事前定義済み型から新しい型を定義した場合、下記の様な記述が可能となる。
Goには継承が意図的に実装されていない。しかし匿名フィールドという機能を用いることで、ある構造体と同じフィールド、メソッドを持つ構造体を容易に作成することができる。
このようにして作られた構造体から匿名フィールドで用いられた元となる構造体の型に暗黙的にキャストするような機能は存在していない。
GoにはC++や他の言語における仮想関数を持ったクラスが存在しない。型に追加したメソッドは一種の非仮想関数である。Goにおいての多態はinterface型を使用して実現する。
interface型は実装を一切持たずメソッドの形式だけを定義した型であり、その点はC#など最近の言語のinterfaceと同じである。但し、Goのinterface型は、代入できる型との関連付けが不要である。interfaceに定義しているメソッドを全て持っていればどんなオブジェクトでも代入可能である。
Goにおけるinterfaceの例を下記に示す。
Goのinterfaceは、MLのsignatureや、かつてg++に存在したsignatureとC++拡張と全く同じ機能である。
ではcodice_7文という例外安全な強制実行のしくみを採用している。
codice_7はcodice_7キーワードに続けて、関数呼び出しかセレクターによる呼び出しを記述することで関数終了時に指定した処理の呼び出しを実行する。
codice_7は下記の様に記述する。
codice_7はブロックを持たず入れ子が深くなるようなことはない。ただし、関数以外のブロックを無視する点に注意が必要である。例えばループ中でcodice_7を使用した場合、ループ内では指定した関数が呼ばれず関数終了時にcodice_7で指定した全ての関数呼び出しが行われる。
codice_7には、関数呼び出しかセレクターによる呼び出ししか記述できず、式や文を直接記述することはできないが、下記のように無名関数を利用して、任意の式や文の実行も可能である。
他の言語で使われているcodice_15方式の例外処理機能はないが代わりの機能としてcodice_16とcodice_17を用いた例外処理機能を提供している。は一般的な例外処理への使用を推奨しないものの、例外処理用の専用構文を備えている。一般的な例外にはあくまで戻り値を使う。
例外を陽に発生させる仕組みとしてcodice_16関数がある。
codice_16 は下記のように記述する
codice_16関数の引数には、数値や関数、構造体といった各種値を指定する事が出来る。特定型のデータでなければ使えないといった制限はない。また、codice_16は構文ではなく関数である。有用性は無いが、codice_7など式が使えず関数呼び出ししか記述できない場所でも直接記述できる。
codice_16関数を実行するとcodice_16呼び出し以降の処理を中断し、コールスタックを巻き戻す。 ただし、codice_16呼び出し以前にcodice_7された関数やセレクターについては呼び出しが実行される。
codice_16関数で投じられた例外データは、codice_17関数と、codice_7を組み合わせて受け取る。codice_17関数は、codice_16関数の引数を返し、コールスタックの巻き戻しを停止する。
codice_17の使用例を下記に示す。
codice_17は構文ではなく関数であるためcodice_7に codice_35 と直接記述することもできる。ただし、codice_17が機能するのはcodice_7で呼び出した関数の内部だけであり、codice_7に直接記述した場合は機能しない。
codice_17はcodice_7で実行される関数内であればどこでも機能する。これを利用し例外が発生する関数に直接codice_17を記述せず、例外処理用関数を用意してそこにcodice_17を記述し、共通する例外処理を一つの関数にまとめる事もできる。処理をまとめることができるが記述が冗長となる。
のcodice_7とcodice_16関数・codice_17関数の組み合わせでは、codice_7で起きたcodice_16もcodice_17で捕まえられる。
はインターフェース型の値から、基底型の値（インターフェース型に変換される前の型の値）を動的に安全に得るダウンキャストの仕組みとして「型アサーション」と呼ばれる機能を備えている。
標準パッケージのreflectを使うことで、対象の値型やその値などの詳細を得ることができる。
には名前とモジュールを管理するために、パッケージという仕組みを持っている。
基本的なパッケージの使用例を下記に示す。
には多彩なcodice_49文が存在するが、その構成要素は、別名の指定とのソースを格納したフォルダーの指定（またはパッケージバイナリー）という非常に単純なものである。では名前管理とモジュールの取り込み指定を一つの構文にまとめる事で、他の言語では煩わしいモジュールの結合を簡潔なものとしている。
の名前管理の特筆する点として名前解決の方法として階層型の名前空間ではなく別名の仕組（のみ）を採用している点が挙げられる。名前解決をするために長い名前を記述する煩わしさはない。
更ににはモジュール管理の点でも特筆すべき点がある。はソースファイル中に一つ初期化関数（codice_50）を定義する事で、初期化関数により実行時に広域変数を初期化できるという機能を持っている。この初期化関数が呼ばれるソースファイルは、codice_51関数の定義されたソースファイルから連鎖的にcodice_49されたパッケージに含まれるソースファイルだけである。この特性により使う予定もないのに初期化コードが実行されるおそれはない。また、パッケージが初めて参照されるまで初期化が遅延されてしまうという事もない。
には、型レベルのアクセス指定子が存在しないが、パッケージレベルでのアクセス制御が存在する。パッケージレベルでのアクセス制限はシンボル名（変数名、メソッド名、関数など）の先頭一文字目が大文字か小文字かで決定する。大文字であればパッケージに対し公開され、小文字であれば非公開となる。
型の継承、ジェネリックプログラミング、アサーション、オーバーロードといった機能をあえて提供していない。FAQにおいて、ジェネリックプログラミングは一部導入が表明されているが、オーバーロードは効率的見地から排除されたことが述べられている。関数は多値を返すことができるので、それによりエラーの報告は容易である、としている。
Go言語の処理系は2種類ある。
codice_53はGo言語で実装されたセルフホスティングのGo言語コンパイラである。バージョン1.4以前はC言語で実装されていたが、バージョン1.5でC言語からGo言語への変換ツールでコンパイラの実装言語を切り替えて、以降はGo言語で開発している。構文解析にyacc・bisonを使用している。
codice_54は、再帰下降パーサを持つC++フロントエンド、バックエンドに標準GCCを利用したサードパーティー開発のGo言語コンパイラである。