Go言語_関数
関数の記述方法
基本形
Go言語では、関数を以下の形式で定義します。
戻り値の型を引数の後ろに記述する特徴があります。
func 関数名(引数) 戻り値の型 {
return 戻り値
}
関数名とプライベート関数
関数名が小文字から始まる場合はその関数は他のパッケージから使用できません。
つまり、プライベート関数になります。
関数名が大文字から始まる場合はその関数は他のパッケージから呼び出すことができます。
os.Exit()などのように、パッケージ関数が大文字で始まる理由はこのためです。
複数の戻り値
Go言語の関数は「多値返却」が可能です。
package main
import (
"fmt"
)
func add(x int, y int) int {
return x + y
}
func sub(x, y int) int {
return x - y
}
func addAndSub(x, y int) (int, int) {
return x + y, x - y
}
func main() {
a := add(300, 200)
b := sub(300, 200)
c, d := addAndSub(300, 200)
fmt.Printf("a=%d, b=%d, c=%d, d=%d\n", a, b, c, d)
}
多値返却は、特にエラー処理をするためによく使われます。
package main
import (
"errors"
"fmt"
"os"
)
func division(x, y int) (int, error) {
if y == 0 {
return 0, errors.New("Invalid number")
}
return x / y, nil
}
func main() {
ans, err := division(90, 20)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Println(ans)
}
なお、Go言語では宣言した変数を使わないとコンパイルエラーになります。
そのため、多値返却で利用しない値を返却する場合、アンダースコアで受け取る必要があります。
// エラーを無視する場合
ans, _ := division(12, 0)
fmt.Println(ans)
可変引数
Go言語の可変引数指定は「...」を記述します。
可変長引数は暗黙的に値を配列にコピーして関数全体のスライスに渡されます。
package main
import (
"fmt"
)
func print_msg(messages ...string) {
fmt.Printf("messages length = %d\n", len(messages))
for index, msg := range messages{
fmt.Printf("messages[%d] = %s\n", index, msg)
}
}
func main() {
print_msg("The", "Go", "Programming", "Language")
}
関数値
Go言語の関数はファーストクラスであり、関数は型を持ちます。
つまり、関数を変数に代入したり、関数の引数や戻り値に関数を指定できるということです。
package main
import (
"fmt"
)
func addition(num1 int, num2 int) int {
return num1 + num2
}
// 戻り値に関数を返す関数です
func subtraction() func(int, int) int {
return func(num1 int, num2 int) int { return num1 - num2 }
}
func multiplication(num1 int, num2 int) int {
return num1 * num2
}
func division(num1 int, num2 int) int {
if num2 == 0 {
return 0
}
return num1 / num2
}
// 第三引数は演算用関数を指定する。
func calcByMethod(num1 int, num2 int, method func(int, int) int) int {
return method(num1, num2)
}
func main() {
// 関数を変数に代入する。
add := addition
ans1 := add(20, 5) // 25
// 関数の戻り値から関数を取得する。
sub := subtraction()
ans2 := sub(20, 5) // 15
// 引数に関数を指定する。
ans3 := calcByMethod(20, 5, multiplication) // 100
ans4 := calcByMethod(20, 5, division) // 4
fmt.Printf("%d, %d, %d, %d\n", ans1, ans2, ans3, ans4)
}
無名関数
無名関数を変数に格納して、その変数を経由して無名関数を実行することができます。
package main
import (
"fmt"
)
func main() {
addTag := func(str string) string { return "<" + str + ">" }
tag := addTag("class-view")
fmt.Printf("%s\n", tag)
}
クロージャ
Goの関数は クロージャ(closure)です。
クロージャとは、その関数が定義された環境への参照を持った関数という意味です。
例えば、1から10までの数字を全て足す処理は以下のように記述できます。
package main
import "fmt"
func addSum() func(int) (int, int) {
sum := 0 // 合計値を格納する変数
return func(num int) (int, int) {
sum = sum + num
return num, sum
}
}
func main() {
calc := addSum()
for i := 1; i <= 10; i++ {
addVal, sumVal := calc(i)
fmt.Printf("add value: %d -> sum: %d\n", addVal, sumVal)
}
}
sum変数はクロージャに属する変数として利用されます。
クロージャで束縛された変数領域は、クロージャが参照され続ける限りは破棄されることがありません。
そのため、前回までの合計値をsum変数に保持することができています。
上記プログラムの実行結果は以下の通りです。
add value: 1 -> sum: 1
add value: 2 -> sum: 3
...
add value: 9 -> sum: 45
add value: 10 -> sum: 55
関連ページ
- Go言語_プログラムの作成
- Go言語_コマンドライン引数
- Go言語_変数と型
- Go言語_コンポジット型
- Go言語_制御構文
- Go言語_関数
- Go言語_演算子
- Go言語_メソッド
- Go言語_インターフェース