Go 言語における関数

GolangGolangBeginner
今すぐ練習

💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください

はじめに

プロジェクトの複雑さが増すにつれて、コードを複数の関数に分割することが一般的です。このアプローチは、コードの読みやすさを向上させ、コラボレーションを容易にし、コードを複製することなくロジックを迅速に再利用できるようにします。この実験では、Go言語で関数を作成して使用する基本を学びます。独自の関数を定義する方法、Go言語がパラメータと戻り値をどのように処理するかを理解し、init関数と可変長パラメータについて学びます。

主要なトピック

  • 関数とは何か、どのように機能するかを理解すること
  • Go言語で関数を宣言すること
  • 値渡しと参照渡しによるパラメータの渡し方
  • 関数から複数の値を返すこと
  • 環境を設定するためにinit関数を使用すること
  • 柔軟な入力処理のための可変長パラメータを使用すること

Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL go(("Golang")) -.-> go/BasicsGroup(["Basics"]) go(("Golang")) -.-> go/FunctionsandControlFlowGroup(["Functions and Control Flow"]) go(("Golang")) -.-> go/ErrorHandlingGroup(["Error Handling"]) go/BasicsGroup -.-> go/values("Values") go/BasicsGroup -.-> go/variables("Variables") go/FunctionsandControlFlowGroup -.-> go/for("For") go/FunctionsandControlFlowGroup -.-> go/if_else("If Else") go/FunctionsandControlFlowGroup -.-> go/functions("Functions") go/ErrorHandlingGroup -.-> go/errors("Errors") subgraph Lab Skills go/values -.-> lab-149098{{"Go 言語における関数"}} go/variables -.-> lab-149098{{"Go 言語における関数"}} go/for -.-> lab-149098{{"Go 言語における関数"}} go/if_else -.-> lab-149098{{"Go 言語における関数"}} go/functions -.-> lab-149098{{"Go 言語における関数"}} go/errors -.-> lab-149098{{"Go 言語における関数"}} end

基本的なプログラムの作成と実行

まず、プロジェクトディレクトリに移動してGoファイルを作成します。

cd ~/project
touch func.go

func.goを開くためのテキストエディタを使用して、次のコードを追加します。

package main

import "fmt"

func main() {
    a1, b1 := 12, 4
    a2, b2 := 12, 0

    // 最初のペアについて
    if b1 == 0 {
        fmt.Println("The divisor cannot be 0")
    } else {
        fmt.Println(a1 / b1)
    }

    // 2番目のペアについて
    if b2 == 0 {
        fmt.Println("The divisor cannot be 0")
    } else {
        fmt.Println(a2 / b2)
    }
}

このコードは2つの除算操作を試み、除算前にゼロ除算をチェックします。除算対象がゼロの場合、エラーメッセージを表示します。

プログラムを実行します。

go run func.go

次のように表示されるはずです。

3
The divisor cannot be 0

関数宣言

以前の実験では、プログラムが簡単であれ複雑であれ、操作にはmain関数のみを使用してきました。

プログラムは1つのmain関数のみを持つことができ、これはプログラムのエントリポイントです。プログラムを実行すると、他の関数がmain関数内で直接または間接的に呼び出されて実行されます。

では、関数の構文を見てみましょう。

func functionName(parameters...)(returnValues...){
    code block
}

ここで、関数名は関数を識別するために使用されます。関数名には次のルールが適用されます。

  • 英字、数字、アンダースコアで構成できます。ただし、関数名の最初の文字は数字ではなければなりません。たとえば、func 3ab(){}は無効です。
  • 最初の文字が大文字の場合、外部パッケージのコードから参照できます。最初の文字が小文字の場合、パッケージ内でのみ使用できます。これは、パブリック関数とプライベート関数に似ています。

パラメータリストは、関数に渡されるパラメータの数と型を宣言します。

  • パラメータリストは空でもよく、複数のパラメータを含んでもよいです。

  • 各パラメータは、パラメータ名とパラメータ型で構成されます。たとえば、次のパラメータリストでは、int型の2つの変数を宣言しています。

    func test(a, b int) (res int){}

戻り値リストは、関数の実行後に必要な値を返すために使用されます。

  • 戻り値リストはパラメータリストと似ています。パラメータの数は任意の値です。

  • 一般的に、戻り値リストは変数名と変数型で構成され、変数名は省略可能です。

  • 1つの変数のみを返し、変数型のみを宣言する場合、丸括弧を省略できます。たとえば:

    func test(a int, b string) int{}

パラメータ型が同じ場合、短縮表記モードを使用できます。次の2つの関数は同じ機能を持っています。

func test(a, b int, c, d string)(res1, res2 int, res3 string){}

// 短縮表記モード
func test(a, b int, c, d string)(res1, res2 int, res3 string){}

func.goの内容を次のコードに置き換えます。

package main

import "fmt"

func check(divisor int) bool {
    if divisor == 0 {
        fmt.Println("The divisor cannot be 0")
        return false
    }
    return true
}

func main() {
    a1, b1 := 12, 4
    a2, b2 := 12, 0

    // 除算前にcheck関数を使用する
    if check(b1) {
        fmt.Println(a1 / b1)
    }
    if check(b2) {
        fmt.Println(a2 / b2)
    }
}

再度、プログラムを実行します。

go run func.go

同じ出力が表示されるはずです。

3
The divisor cannot be 0

今回は、チェックロジックがcheck関数にカプセル化されており、コードがクリーンになり、再利用性が向上しています。

init関数の使用

Go言語は、main関数の前に実行されるinit関数をサポートしています。これは、主な実行前に環境条件を設定したり、変数を初期化するために頻繁に使用されます。

func.goの内容を以下のものに置き換えます。

package main

import "fmt"

func init() {
    fmt.Println("init statement")
}

func main() {
    fmt.Println("main statement")
}

プログラムを実行します。

go run func.go

以下のように表示されるはずです。

init statement
main statement

Go言語において、init関数は以下の特徴を持っています。

  • 入力パラメータや戻り値はありません。
  • 他の関数から呼び出すことはできません。

同じコードファイルまたは同じパッケージには複数のinit関数が存在することができます。実行順序は以下の通りです。

  • 同じコードファイル内でより早く現れるinit関数が先に実行されます。
  • 同じpackage内でアルファベット順が早いファイルが先に実行されます。たとえば、同じpackageに以下のようなinit関数を持つファイルがある場合:
a1.go
a2.go
b1.go

実行順序はa1.goa2.gob1.goになります。なぜなら、a > bであり、1 < 2だからです。

関数から複数の値を返す

Go言語では、関数が複数の値を返すことができます。これは、一度にいくつかの関連する計算を行う際に便利です。

func.goの内容を以下のものに置き換えます。

package main

import "fmt"

func cal(a, b int) (int, int, int, int) {
    return a + b, a - b, a * b, a % b
}

func main() {
    add, sub, mul, rem := cal(90, 12)
    fmt.Println(add, sub, mul, rem)
}

プログラムを実行します。

go run func.go

以下のように表示されるはずです。

102 78 1080 6

ここでは、cal関数が一度に4つの値を返しており、複数の戻り値が特定のタスクを簡素化する方法を示しています。

可変長パラメータの使用

可変長パラメータを使うと、関数が可変個の引数を受け取ることができます。これは、入力サイズが固定されていないシナリオを簡素化することができます。

func.goの内容を以下のものに置き換えます。

package main

import "fmt"

func printX(values...string) {
    for _, v := range values {
        fmt.Println(v)
    }
}

func main() {
    printX("labex", "labs", "courses")
}

プログラムを実行します。

go run func.go

以下のように表示されるはずです。

labex
labs
courses

printX関数は任意の数の文字列を引数として受け取ることができ、使いやすく柔軟性があります。

まとめ

この実験では、Go言語における関数の定義と使用方法を学びました。複数の値を返す方法や、可変個のパラメータを受け取る方法も学びました。また、init関数がmain関数の前に実行される仕組みも見てきました。コードを関数にまとめることで、プログラムを理解しやすく、保守しやすく、再利用しやすくすることができます。

これらのスキルは、モジュール化された拡張可能なGoアプリケーションを構築するための基礎となります。プロジェクトが拡大するにつれて、関数を使ってコードとロジックを整理することはますます重要になります。