Ubuntuで最初の並行Goプログラムを書く
GoogleのGoプログラミング言語は2009年から存在し、2012年には公式のv1.0ステータスに達しました。その間に、多くのことが変わり、言語のインストール方法も変わりました。初期の頃は、公式のバイナリ配布がなく、ソースコードからGoをビルドする必要がありました。これは、言語が頻繁に変更されていたため、推奨される方法でした。また、Linuxディストリビューション用のプリビルドパッケージを使用することもできました。当時、Windowsサポートは限られており、Intel以外のCPUアーキテクチャのサポートも限られていました。
それ以来、状況は大きく改善されました。Linuxでは、Goをインストールするための簡単な方法が2つあります。Goのダウンロードページから公式のLinuxバイナリビルドをダウンロードするか、Linuxディストリビューション用のプリビルドパッケージを選択します。UbuntuにGoをインストールする最も簡単な方法は、apt-getを使用することです:
sudo apt-get install golangGoがインストールされると、プログラムの開発を開始できます。最もシンプルなGoプログラムの1つは、クラシックな「Hello World!」プログラムです。テキストエディタを使用して、次の短いGoコードを含む「hellomte.go」という名前のファイルを作成します:
package main
import "fmt"
func main() {
fmt.Println("Hello Make Tech Easier!")
}Goのv1.0以降、個別のコンパイルおよびリンクコマンドの必要がなくなり、古い8gおよび8lコマンドはgoコマンドに置き換えられました。
hellomte.goを実行するには、ターミナルを開き、ソースコードファイルが含まれているフォルダにディレクトリを変更し、次のように入力します:
go run hellomte.goこれにより、Goプログラムがコンパイルされて実行されますが、実行可能なバイナリは生成されません。バイナリを作成して実行するには、go buildコマンドを使用します:
go build hellomte.go
./hellomte並行性の力
Goプログラミング言語の定義的な特徴の1つは、並行性をサポートしていることで、これによりプログラムは複数のタスクを同時に処理できます。並列性は並行性に似ていますが、プログラムが多くのタスクを同時に実行できるようにしますが、並行性はこれらの別々のタスクが通信し、相互作用できるようにする点で一歩進んでいます。その結果、Goはプログラマーにワーカープール、パイプライン(1つのタスクが別のタスクの後に発生する)、および同期または非同期のバックグラウンドタスクなど、さまざまな並行設計を使用することを許可します。この並行性の基盤は、goroutineとchannels、およびGoのselectステートメントです。
以下は、並行するgoroutineを使用して文字列を何度も印刷するシンプルなGoプログラムです:
package main
import (
"fmt"
"time"
)
func say(s string) {
for i := 0; i < 5; i++ {
fmt.Println(s)
}
}
func main() {
go say("Hello Make Tech Easier!")
fmt.Println("少し眠る...")
time.Sleep(100 * time.Millisecond)
}say()関数は、文字列(パラメータs)を5回印刷する単純なループを実行します。興味深いのは、その関数がどのように呼び出されるかです。say("Hello Make Tech Easier!")と呼び出すのではなく、関数呼び出しの前にgoキーワードが置かれています。これは、関数が別のタスクとして実行されることを意味します。main()関数の残りは、goroutineが完了するための時間を与えるために少し眠ります。
出力はあなたを驚かせるかもしれません:

ご覧のとおり、say()関数はgoroutineとして実行されており、設定中にmain()関数の残りが続行され、少し眠る...を印刷し、その後眠りに入ります。その頃には、goroutineがアクティブになり、文字列を5回印刷し始めます。最終的に、プログラムはタイムアウト制限に達すると終了します。
チャンネル
goroutinesはチャンネルを使用して通信できます。チャンネルは、Goプログラムの2つの異なる部分の間に通信のラインを開きます。通常、関数はgoroutineとして呼び出され、データを返す必要がある場合(ネットワーク操作からなど)、チャンネルを使用してそのデータを渡すことができます。Goプログラムの別の部分がそのデータを待っている場合、データが準備できるまで眠ります。チャンネルはmake()関数を使用して作成され、goroutinesにパラメータとして渡すことができます。
このコードを考えてみてください:
package main
import (
"fmt"
)
func say(s string, c chan int) {
var i int
for i = 0; i < 5; i++ {
fmt.Println(s)
}
c <- i
}
func main() {
c := make(chan int)
go say("Hello Make Tech Easier!", c)
sts := <- c
fmt.Println(sts)
}say()関数は、最初の例と非常に似ていますが、2番目のパラメータがチャンネルであり、文字列を印刷した後、反復回数がc <- iの行を介してチャンネルに送信されるという点が異なります。
メイン関数はチャンネルを作成し、say()関数をgoroutineとして開始し、次にチャンネルからデータが来るのを待ち、sts := <- cの後に結果を印刷します。
結論
Go言語はここ数年で大きく進歩しました。最近見ていない場合は、今が良い時期かもしれません!