Go

Go言語入門:基本構文と実践例について解説

Go言語(Go言語)の入門記事では、基本構文や実行速度など、魅力的なポイントを平易な言葉で紹介します。

シンプルな文法のおかげで、初めてのプログラミングにも取り組みやすくなっています。

実際の環境を活用しながら、Goの楽しさを実感してもらえるよう解説します。

開発環境の確認と基本操作

実行方法の再確認

Goの実行方法はシンプルであり、go run ファイル名.goコマンドでプログラムを実行します。

以下のサンプルコードは実行前の環境確認のため、簡単なプログラム例になっています。

package main
import (
	"fmt"
)
func main() {
	// 環境確認用のメッセージを出力する
	fmt.Println("Hello, Go!")
}
Hello, Go!

基本構文の基礎

変数と定数の利用方法

Goではvarキーワードや短縮宣言を用いて変数を定義できます。

また、constを使って定数を定義することが可能です。

以下のサンプルコードでは、変数と定数の定義例を示します。

package main
import (
	"fmt"
)
func main() {
	// 定数の定義(数値と文字列)
	const pi = 3.14          // 円周率の近似値
	const greeting = "こんにちは"
	// 変数の定義(int型)
	var count int = 10
	// 短縮宣言による変数定義(string型)
	name := "Go言語"
	fmt.Println("定数pi:", pi)
	fmt.Println("定数greeting:", greeting)
	fmt.Println("変数count:", count)
	fmt.Println("変数name:", name)
}
定数pi: 3.14
定数greeting: こんにちは
変数count: 10
変数name: Go言語

データ型の基礎

Goの基本的なデータ型には、整数、浮動小数点数、文字列、真偽値などが含まれます。

以下のコードでは、各データ型の利用例を示しています。

package main
import (
	"fmt"
)
func main() {
	// 整数型
	var intValue int = 42
	// 浮動小数点数型
	var floatValue float64 = 3.1415
	// 文字列型
	var stringValue string = "Go言語の世界"
	// 真偽値型
	var boolValue bool = true
	fmt.Println("整数型:", intValue)
	fmt.Println("浮動小数点数型:", floatValue)
	fmt.Println("文字列型:", stringValue)
	fmt.Println("真偽値型:", boolValue)
}
整数型: 42
浮動小数点数型: 3.1415
文字列型: Go言語の世界
真偽値型: true

制御構文の使い方

if文の基本構造

if文は条件に応じた処理を行うために使用します。

以下は基本的なif文の例です。

package main
import (
	"fmt"
)
func main() {
	// 数値の比較
	number := 15
	if number > 10 {
		// 条件がtrueの場合の処理
		fmt.Println("numberは10より大きいです")
	}
}
numberは10より大きいです

for文の基本構造

Goのfor文は唯一のループ構文であり、カウンタ型のループも可能です。

以下は基本的なforループの例です。

package main
import (
	"fmt"
)
func main() {
	// 0から4までの数値を出力する
	for i := 0; i < 5; i++ {
		fmt.Println("ループ番号:", i)
	}
}
ループ番号: 0
ループ番号: 1
ループ番号: 2
ループ番号: 3
ループ番号: 4

switch文の活用

switch文は複数の条件分岐をシンプルに記述するために利用できます。

以下はswitch文を使った例です。

package main
import (
	"fmt"
)
func main() {
	// 曜日を数字から判断する例
	day := 3
	switch day {
	case 1:
		fmt.Println("月曜日")
	case 2:
		fmt.Println("火曜日")
	case 3:
		fmt.Println("水曜日")
	default:
		fmt.Println("その他の日")
	}
}
水曜日

配列、スライス、マップの操作

Goでは配列、スライス、マップなどを利用してデータを管理することができます。

以下のコードでは、それぞれのデータ構造の基本的な使い方を示しています。

package main
import (
	"fmt"
)
func main() {
	// 配列の定義(固定長)
	var array [3]int = [3]int{1, 2, 3}
	// スライスの定義(可変長)
	slice := []string{"apple", "banana", "cherry"}
	// マップの定義(キーと値)
	countryPopulation := map[string]int{
		"Japan":  125800000,
		"Brazil": 212600000,
	}
	fmt.Println("配列の内容:", array)
	fmt.Println("スライスの内容:", slice)
	fmt.Println("マップの内容:", countryPopulation)
}
配列の内容: [1 2 3]
スライスの内容: [apple banana cherry]
マップの内容: map[Brazil:212600000 Japan:125800000]

関数とエラーハンドリング

関数定義の基礎

関数はプログラム内で再利用可能な処理単位です。

Goでは関数の定義がシンプルであり、返り値も複数設定することが可能です。

以下は基本的な関数の定義例です。

package main
import (
	"fmt"
)
// addは2つの整数を受け取り、その和を返す関数
func add(x int, y int) int {
	return x + y
}
func main() {
	// 関数addの実行例
	result := add(5, 7)
	fmt.Println("合計は", result, "です")
}
合計は 12 です

エラーチェックの実装方法

Goの関数ではエラーを返すことが一般的です。

エラーチェックを行うコードはシンプルに記述でき、呼び出し側でエラー処理を行います。

package main
import (
	"errors"
	"fmt"
)
// divideは整数の除算を行い、ゼロ除算の場合はエラーを返す関数
func divide(numerator int, denominator int) (int, error) {
	if denominator == 0 {
		return 0, errors.New("ゼロ除算エラー")
	}
	return numerator / denominator, nil
}
func main() {
	// 関数divideの実行例
	result, err := divide(10, 2)
	if err != nil {
		fmt.Println("エラー:", err)
	} else {
		fmt.Println("結果は", result, "です")
	}
}
結果は 5 です

defer、panic、recoverの利用

Goでは、deferを使って関数終了時に処理を行うことができ、またpanicrecoverでパニック状態の復旧が可能です。

以下のサンプルコードは、意図的なパニックを発生させ、recoverで回復する例です。

package main
import (
	"fmt"
)
// dangerousFunctionは意図的にパニックを発生させる例
func dangerousFunction() {
	// deferでrecoverを呼び出してパニックからの復帰処理を行う
	defer func() {
		if r := recover(); r != nil {
			fmt.Println("パニックを回復しました:", r)
		}
	}()
	// パニックを発生させる
	panic("予期しないエラーが発生しました")
}
func main() {
	fmt.Println("関数dangerousFunction実行前")
	dangerousFunction()
	fmt.Println("関数dangerousFunction実行後")
}
関数dangerousFunction実行前
パニックを回復しました: 予期しないエラーが発生しました
関数dangerousFunction実行後

パッケージとモジュールの管理

packageの基本

Goではすべてのソースコードファイルがパッケージに属しており、package mainを使うことで実行可能なプログラムを作成できます。

下記のコードはパッケージ宣言と基本的な関数実装の例です。

package main
import (
	"fmt"
)
// helloWorldは"Hello, Go!"と出力する関数
func helloWorld() {
	fmt.Println("Hello, Go!")
}
func main() {
	helloWorld()
}
Hello, Go!

モジュールの取り扱い

Go Modulesを用いることで、依存関係の管理が容易になります。

プロジェクトルートでgo mod init <module-name>コマンドを実行し、モジュールを初期化することで、複数のパッケージから構成されるプロジェクトの管理が可能となります。

以下は、モジュールを利用したプロジェクトの基本構造の説明です。

  • プロジェクトルートにgo.modファイルが存在
  • 複数のパッケージに分割したファイルがディレクトリごと配置

実際のコード例は、上記「packageの基本」と同様の実装となるため、ここではコードサンプルは割愛します。

標準ライブラリの活用

入出力とファイル操作(fmt、os)

Goではfmtパッケージを用いた入出力や、osパッケージを利用したファイル操作が可能です。

以下のサンプルコードは、ファイルの作成と内容の出力を行う例です。

package main
import (
	"fmt"
	"os"
)
func main() {
	// "sample.txt"という名前のファイルを作成する
	file, err := os.Create("sample.txt")
	if err != nil {
		fmt.Println("ファイル作成エラー:", err)
		return
	}
	// 関数終了時にファイルを閉じる
	defer file.Close()
	// ファイルにデータを書き込む
	message := "これはファイルに書き込むサンプルです"
	_, err = file.WriteString(message)
	if err != nil {
		fmt.Println("書き込みエラー:", err)
		return
	}
	// 書き込み完了のメッセージの出力
	fmt.Println("ファイルに書き込みが完了しました:", message)
}
ファイルに書き込みが完了しました: これはファイルに書き込むサンプルです

ネットワーク通信(net/httpなど)

Goのnet/httpパッケージを利用することで、HTTPリクエストを簡単に送信できます。

以下は、ウェブサイトからデータを取得するシンプルな例です。

package main
import (
	"fmt"
	"io/ioutil"
	"net/http"
)
func main() {
	// GETリクエストを送信する
	resp, err := http.Get("https://example.com")
	if err != nil {
		fmt.Println("HTTPリクエストエラー:", err)
		return
	}
	defer resp.Body.Close()
	// レスポンスボディを読み込む
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("読み込みエラー:", err)
		return
	}
	// 取得したデータを出力
	fmt.Println("取得したコンテンツ:")
	fmt.Println(string(body))
}
取得したコンテンツ:
<!doctype html>
<html>
  <head>
    <title>Example Domain</title>
    <!-- 以下省略 -->
  </head>
  <body>
    ...
  </body>
</html>

並行処理の基礎

goroutineの利用法

Goは並行処理を簡単に実現できるように設計されており、goroutineを使って軽量なスレッドのような処理を行います。

以下の例は、goroutineを使用して並行処理を行う例です。

package main
import (
	"fmt"
	"time"
)
func concurrentTask(taskID int) {
	// タスクの開始メッセージを出力
	fmt.Printf("タスク%d 開始\n", taskID)
	// 疑似的な処理時間としてスリープ
	time.Sleep(500 * time.Millisecond)
	// タスク完了のメッセージを出力
	fmt.Printf("タスク%d 完了\n", taskID)
}
func main() {
	// 3つのgoroutineを起動する
	for i := 1; i <= 3; i++ {
		go concurrentTask(i)
	}
	// goroutineの終了を待つ目的でスリープ
	time.Sleep(2 * time.Second)
}
タスク1 開始
タスク2 開始
タスク3 開始
タスク1 完了
タスク2 完了
タスク3 完了

channelの基本操作

channelはgoroutine間でデータをやり取りするための手段です。

チャネルを使ってデータを送受信することで、並行処理の同期が可能となります。

以下は、チャネルの基本的な使い方の例です。

package main
import (
	"fmt"
)
func sendData(ch chan string) {
	// チャネルにメッセージを送信する
	ch <- "データ送信完了"
}
func main() {
	// 文字列型のチャネルを作成する
	messageChannel := make(chan string)
	// goroutineを起動し、チャネルにデータを送信
	go sendData(messageChannel)
	// チャネルからデータを受信し、出力する
	message := <-messageChannel
	fmt.Println("チャネルから受信:", message)
}
チャネルから受信: データ送信完了

まとめ

この記事では、Go言語の基本構文から並行処理まで、変数・定数、データ型、制御構文、関数・エラーハンドリング、パッケージ管理、標準ライブラリ、そしてgoroutineやchannelの利用方法を学びました。

実行可能なサンプルコードで具体的な操作手順を確認でき、各要素がどのように連携して動くかを把握できる内容となっています。

ぜひ実際に手を動かして、Go言語の魅力に触れてみてください。

関連記事

Back to top button
目次へ