関数
- Go言語の関数は複数の値を返すことができる
- 関数の中には名称のない匿名関数を作成することができる
-
main()
関数(エントリーポイント)
└引数、戻り値を返さない
└基本的にプロジェクトに1つで、パッケージはmainになる - funcキーワードで開始し、関数名、引数(省略可)、戻り値(省略可)を宣言
基本的な関数の文法
func main() {
result := pls(10, 10)
fmt.Printf("result=%d \n", result)
}
func pls(x int, y int) int {
return x + y
}
// -> result=20
多値を返す関数
- Go言語は関数の戻り値を多値で返すことができる
戻り値の文法(戻り値の型指定のみ)
func 関数名(引数名 型[, .....])(戻り値の型[, ....]){
処理
return 戻り値
}
func main() {
add, sub := calc(10, 20)
fmt.Println(add, sub)
}
func calc(x int, y int) (int, int) {
add := x + y
sub := x - y
return add, sub
}
// -> 30 -10
戻り値の文法(戻り値を変数に代入する)
- 「名前付き戻り値」ともいう。
func 関数名(引数名 型[, .....])(戻り値の変数名 戻り値の型[, ....]){
処理
return 戻り値
}
func main() {
add, sub := calc(10, 20)
fmt.Println(add, sub)
}
func calc(x int, y int) (add int, sub int) {
add = x + y
sub = x - y
return
}
// -> 30 -10
可変長引数
- 引数の型名の前に
...
を入れると、一度に複数の値を渡すことができる。
└関数呼び出し時に暗黙的なスライスが作成される。
func 関数名(引数名...型){
処理
}
func main() {
sum := CalcSum(100, 200, 300, 400)
avg := CalcAvg(100, 200, 300, 400)
fmt.Printf("sum=%d, avg=%d \n", sum, avg)
}
func CalcSum(values ...int) (sum int) {
for _, value := range values {
sum += value
}
return
}
func CalcAvg(values ...int) (avg int) {
for _, value := range values {
avg += value
}
avg = avg / cap(values)
return
}
// -> sum=1000, avg=250
匿名関数(関数リテラル)
- 関数やメソッド内に作成した関数で、名称を持たない
└すぐに呼び出す場合は、関数の最後に()
をつける。
変数に代入して利用する場合
func main() {
// 引数の値を表示する匿名関数を変数functionに代入する
function := func(result int) {
// 引数として受け取った加算結果を出力する
fmt.Printf("答え=%d \n", result)
}
// 加算結果を匿名関数の引数として入力する
function(100 + 200)
}
// -> 答え=300
直ぐに呼び出す場合
※遅延実行で使用する(defer)
func main() {
// 引数の値を表示する匿名関数を直ぐに実行する
func(result int) {
fmt.Printf("答え=%d \n", result)
}(100 + 200)
}
関数型
- 関数を変数に代入するときに使用する
// 加算と減算を戻り値として返す関数
func CalcA(x int, y int) (int, int) {
add := x + y
sub := x - y
return add, sub
}
// 多値の合計を戻り値として返す関数
func CalcSum(values ...int) (sum int) {
for _, value := range values {
sum += value
}
return
}
// 関数型の宣言
type CalcFuncType1 func(int, int) (int, int)
type CalcFuncType2 func(...int) int
func main() {
var func1 CalcFuncType1 = CalcA
add, sub := func1(10, 20)
fmt.Printf("add=%d, sub=%d \n", add, sub)
// 別の変数を使用すれば、同じ関数型を使用することができる
var func2 CalcFuncType1 = CalcA
add, sub = func2(20, 30)
fmt.Printf("add=%d, sub=%d \n", add, sub)
var func3 CalcFuncType2 = CalcSum
sum := func3(100, 200, 300, 400)
fmt.Printf("sum=%d \n", sum)
}
// -> add=30, sub=-10
// add=50, sub=-10
// sum=1000
遅延実行
- 関数呼び出しにキーワード
defer
をつけると、遅延実行することができる。
└遅延実行は、defer
を記述した関数の処理が全て終わったときに実行される
└パニックが発生しても遅延実行の関数は必ず実行される
└関数内喉の場所に記述しても、最後に実行される
└ループ処理内で遅延実行されると、実行を置いておくことができ、LIFO形式で実行される
func Message(msg string) {
fmt.Println(msg)
}
func main() {
defer Message("message1")
fmt.Println("実行")
defer Message("message2")
}
// LIFO形式で実行される
// -> 実行
// message2
// message1
ループ内で実行
func message(msg string) {
fmt.Println(msg)
}
func main() {
for i := 0; i < 5; i++ {
fmt.Println("実行 i=", i)
defer message(fmt.Sprintf("メッセージ%d", i))
}
}
// -> 実行 i= 0
// 実行 i= 1
// 実行 i= 2
// 実行 i= 3
// 実行 i= 4
// メッセージ4
// メッセージ3
// メッセージ2
// メッセージ1
// メッセージ0