Edited at

golangを基礎から学ぶ 関数編

More than 3 years have passed since last update.


関数は複数の戻り値をもつことができる

golangの目新しい特徴のひとつとして数えられている。

関数は、括弧でリストすることで複数の値を持かえすことができる。返された値は、変数リストへ代入して格納する。

(int, int) が返す値を括弧でリストしている部分。

func 関数名 引数 戻り値 の順番になる。

func f(a int, b int) (int, int) {

c := a + b
d := a * b
return c, d
}

func main() {
a := 100
b := 100
c,d := f(a, b)
fmt.Println(c)
fmt.Println(d)
}

output

200

10000

戻り値を複数定義できる形式はエラーハンドリングにも一役かっている

func doSomething(input int) (result string, err error) {

switch {
case input < 0:
return "", fmt.Errorf("%d is minus value", input)
case input < 10:
return "less than 10", nil
default:
return "greater than 10", nil
}
}

func main() {
if r, err := doSomething(-1); err != nil {
fmt.Println(err)
} else {
fmt.Println(r)
}
}

output

-1 is minus value


匿名関数

golangは匿名関数をサポートしている

funcから始まる関数リテラルは匿名関数をあらわし、変数に代入することが可能。

func main() {

fn := func() {
fmt.Println("hello")
}
fn()
}

output

hello

匿名関数を関数の引数にとしてわたすことも可能

func sumOf(f func(int) int, n, m int) int {

a := 0
for ; n <= m; n++ {
a += f(n)
}
return a
}

func main() {
square := func(x int) int { return x * x }
fmt.Println(square(10))
a := func(x int) int { return x * x }(10)
fmt.Println(a)
fmt.Println(sumOf(square, 1, 100))
fmt.Println(sumOf(func(x int) int { return x * x }, 1, 100))
}

output

100

100
338350
338350


クロージャ

関数リテラルはクロージャになっている。

そのため関数リテラル内から外側の関数内で定義した変数を参照可能になる。

これらの変数は外側の関数と、関数リテラル間で共有され、これらからアクセス可能な限り存続する。

func main() {

x := 5
fn := func() {
fmt.Println("x is", x)
}
fn()
x++
fn()
}

output

x is 5

x is 6

func intSeq() func() int {

i := 0
return func() int {
i += 1
return i
}
}

func main() {
nextInt := intSeq()

fmt.Println(nextInt())
fmt.Println(nextInt())
fmt.Println(nextInt())
newInts := intSeq()
fmt.Println(newInts())
}

output

1

2
3
1


参考

golang で複数のエラーをハンドリングする方法

お気楽 Go 言語プログラミング入門

Function Types in Go (golang)