Go言語の基礎: 初心者向けガイド

2023 / 12 / 30

Go言語の基礎知識をまとめてみました。

Go言語の基礎: 初心者向けガイド見出し「Go言語の基礎: 初心者向けガイド」

Go言語とは見出し「Go言語とは」

Go言語は、C言語の構文やシンプルさを継承しつつ、並行処理に関してはCSP (Communicating Sequential Processes) モデルに基づいています。また、Pascal言語からの影響も見られ、エラー処理におけるdefer、panic、recoverなどのメカニズムはPascalの考え方に基づいています。

Goの並行処理における特徴であるゴルーチン(goroutine)とチャネル(channel)は、CSPモデルに基づいた概念を取り入れており、効率的かつ安全な並行処理を実現しています。

なぜGoを学ぶべきか?見出し「なぜGoを学ぶべきか?」

  • 簡潔でわかりやすい構文: Go言語はシンプルで読みやすい構文を持っています。
  • 効率的な並行処理: ゴルーチン(goroutine)とチャネル(channel)を使った並行処理は非常に強力です。
  • 高性能: コンパイル言語でありながら、高速な実行を可能にします。
  • 豊富な標準ライブラリ: 標準ライブラリには多くの便利なツールや機能が含まれています。

Go言語の基本構文見出し「Go言語の基本構文」

Go言語の基礎となる構文を学ぶことは、言語を理解する上で非常に重要です。主な概念としては以下があります:

  • 標準入出力: 変数や文字列をターミナルへ出力、またはターミナルから入力。
  • 変数と定数: 変数の宣言や初期化、定数の使い方など。
  • 制御構造: if文、forループ、switch文などの制御構造の使い方。
  • 関数: 関数の定義、引数と返り値、再帰など。

それぞれについて、詳しくみていきましょう。

標準入出力見出し「標準入出力」

Go言語では、標準入力(キーボードからの入力)と標準出力(画面への出力)を簡単に扱うことができます。主にfmtパッケージが標準入出力を扱うために利用されます。
従って利用には次の1文が必要です。

import "fmt"

標準出力

標準出力を使って情報を画面に表示するには、fmtパッケージのPrintlnPrintfなどの関数を利用します。

package main

import "fmt"

func main() {
    fmt.Println("Hello, World!") // 改行付きでテキストを出力
    fmt.Printf("Value: %d\n", 42) // フォーマットを指定して出力
}

PrintlnとPrintfの違いについてもう少し詳しくみてみましょう。

Println関数

  • 改行: Println関数は、引数として与えられた値を順に出力し、最後に改行を追加します。
  • 変数の型: 引数として与えられた変数の型に応じて、適切な形式で出力されます。
  • 複数の引数: 複数の引数を受け取ることができ、それらをスペースで区切って出力します。
    例えば、以下のようなコードを考えましょう:
a := 10
b := "Hello"

println("Value of a:", a, "and value of b:", b)

これは、aの値とbの値をスペースで区切って出力し、最後に改行を追加します。出力は以下のようになります:

Value of a: 10 and value of b: Hello

Printf関数

  • フォーマット指定: Printf関数は、フォーマット指定子を使って出力の形式を制御できます。%d%sなどのフォーマット指定子を使用して、出力する変数の型や表示形式を指定できます。
  • 改行: フォーマット指定子の最後に改行文字\nを追加する必要があります。改行が含まれていない場合は改行されません。
    例えば、以下のようなコードを考えましょう:
a := 10
b := "Hello"

fmt.Printf("Value of a: %d and value of b: %s\n", a, b)

この場合、%dは整数型の変数を、%sは文字列型の変数を表し、それぞれの変数の値が指定されたフォーマットに従って出力されます。最後に\nを使って改行が追加されます。

標準入力
標準入力を使ってユーザーからの入力を受け取るには、fmtパッケージのScanやScanln、Scanfなどの関数を使用します。
ここでもScanとScanln、Scanfには少し違いがありますので、それぞれ見てみましょう。
Scan関数

  • スペース区切り: Scan関数は、スペース(空白文字)までの入力を一つのデータとして扱います。スペースまでの文字列を1つの変数に格納し、次のスペースまでの文字列を別の変数に格納するといった動作をします。
  • 改行: ユーザーが改行を入力するまで、Scan関数はデータの読み取りを続けます。
var name string
var age int

fmt.Print("Enter name and age: ")
fmt.Scan(&name, &age)
fmt.Println("Name:", name, "Age:", age)

この場合、ユーザーが"John 25"と入力すると、name変数に"John"が、age変数に25が格納されます。

Scanln関数

  • 改行での終了: Scanln関数は、改行文字(Enterキー)までの入力を1行として扱います。つまり、改行までの全てのデータを一つの変数に格納します。
  • 改行: ユーザーがEnterキーを押すことで、Scanln関数はデータの読み取りを終了します。
    例えば、以下のようなコードを考えましょう:
var input string

fmt.Print("Enter some text: ")
fmt.Scanln(&input)
fmt.Println("You entered:", input)

この場合、ユーザーが"Hello World"と入力してEnterキーを押すと、input変数に"Hello World"が格納されます。

Scanf関数
Scanf関数はC言語のscanfと同様の動作をします。指定されたフォーマットに基づいて、入力されたデータを解析し、指定された変数に格納します。

例えば、以下のように使用できます:

var name string
var age int

fmt.Print("Enter name and age: ")
fmt.Scanf("%s %d", &name, &age)
fmt.Println("Name:", name, "Age:", age)

この例では、%sは文字列、%dは整数を期待しています。ユーザーが"John 25"と入力すると、name変数に"John"が、age変数に25が格納されます。

誤った型が入力された場合
標準入力において、変数の型と異なるデータが入力された場合、プログラムはその入力を変数の型に従って解釈しようとします。しかし、その変換ができない場合、予期せぬ動作が起こる可能性があります。

具体的には、以下のような状況が考えられます:

  1. データ型の不一致: 例えば、整数型の変数に文字列が入力された場合、Goはその文字列を整数に変換しようとします。しかし、文字列が整数表現ではない場合(例えば、"abc"など)、変換に失敗し、エラーが発生します。
  2. 読み取りの中断: データ型の不一致が検出されると、プログラムは入力の読み取りを中断し、エラーを報告します。この場合、通常はエラーメッセージや例外が発生し、プログラムの実行が停止します。

従って、確実に型がわかっている場合以外は、入力を受け付ける際にエラーハンドリングを追加する必要があります。

変数と定数見出し「変数と定数」

Go言語で利用できる基本的な型

数値型

  • int: 符号付き整数
  • uint: 符号なし整数
  • int8, int16, int32, int64: 符号付き整数のサイズ指定
  • uint8, uint16, uint32, uint64: 符号なし整数のサイズ指定
  • uintptr: ポインタのサイズを表す符号なし整数型
  • float32, float64: 浮動小数点数
  • complex64, complex128: 複素数

ブール型

  • bool: 真偽値

文字列型

  • string: 文字列

その他

  • byte: uint8と同義、バイトデータを表す
  • rune: int32と同義、Unicodeのコードポイントを表す

Go言語ではこれらの基本的な型を使用して様々なデータを表現し、プログラムを記述します。それぞれの型は特定のデータを保持し、プログラム内で使われる異なる目的に適しています。

Go言語では、変数と定数の宣言、初期化、使用方法が以下のようになります。

変数の宣言と初期化

var age int // 変数の宣言
age = 28    // 変数への値の代入

var name string = "Alice" // 変数の宣言と初期化を同時に行う

score := 95 // 短縮宣言を使って変数を宣言と初期化を同時に行う

短縮宣言 :=

:=はGo言語で変数を簡潔に宣言して初期化する方法です。この記法を使うと、変数の型を明示的に書く必要がなくなり、より短くコードを書くことができます。

Go言語では、変数の型をコンパイラが自動的に推論するため、:=を使うことで型を明示的に書かずに済みます。
この方法はコードを短く保ちながらも、変数を宣言して初期化するのに便利です。ただし、この書き方は関数内でのみ使用可能で、関数外ではvarキーワードを使った宣言が必要です。

定数の使用

const pi = 3.14 // 定数の宣言

制御構造見出し「制御構造」

Go言語の制御構造には以下のようなものがあります。

if文とelse if文

num := 10
if num > 5 {
    fmt.Println("Number is greater than 5")
} else if num == 5 {
    fmt.Println("Number is equal to 5")
} else {
    fmt.Println("Number is less than 5")
}

forループ

for i := 0; i < 5; i++ {
    fmt.Println(i)
}

switch文

fruit := "apple"
switch fruit {
case "apple":
    fmt.Println("It's an apple")
case "banana":
    fmt.Println("It's a banana")
default:
    fmt.Println("Unknown fruit")
}

関数見出し「関数」

Goでは次のようにして関数を定義します。
関数の定義

func add(a, b int) int {
    return a + b
}

func main() {
    result := add(3, 5)
    fmt.Println("Sum:", result)
}

引数と返り値見出し「引数と返り値」

関数は引数を受け取り、必要に応じて返り値を返すことができます。

func calculate(a, b int) (int, int) {
    sum := a + b
    diff := a - b
    return sum, diff
}

func main() {
    result1, result2 := calculate(10, 5)
    fmt.Println("Sum:", result1, "Difference:", result2)
}

Goの最初のプログラム見出し「Goの最初のプログラム」

package main

import "fmt"

func main() {
    fmt.Println("Hello, Go!")
}