LoginSignup
2
0

More than 3 years have passed since last update.

Goの関数について

Last updated at Posted at 2020-11-01

関数の基本構文

関数定義の基本形は下記のようになります。

func 関数名(引数) 戻り値型 {
   処理の内容...
}

関数に対して引数を取り、関数の戻り値を指定して、処理内容を書いていく流れです。

名前付き関数

では、簡単な関数を定義してみます。

main.go
func test(x, y int) int {
   a := x * y
   return a
}

func main() {
   fmt.Println(test(10, 5))  //50
}

関数testをint型のx, yで定義し、戻り値型にint型を指定しています。変数aに処理を代入し、returnした値をmain関数で受け取り、値を指定して出力しています。

また、戻り値は複数返すことができます。

main.go
func test(x, y int) (int, int) {
   a := x * y
   b := x / y
   return a, b
}

func main() {
   a, b := test(10, 5)
   fmt.Println(a, b)  //50 2
}

下記のように、戻り値型を省略することで戻り値のない関数も定義できます。

main.go
func test() {
    fmt.Println("こんにちは!")
    return
}

func main(){
   test()  //こんにちは!
}

エラー処理

エラー処理は下記のようなイディオムがあります。

main.go
import (
   "os"
   "log"
)

func main() {
   _, err := os.Open("test.txt")
   if err != nil {
      log.Fatal(err)
  }
}

このプログラムは、ファイルをオープンする際に、エラーがあればエラーメッセージとともに出力する処理です。そのため、osパッケージとlogパッケージをインポートしています。

無名関数

無名関数は、明示的に定義する名前付き関数と違い、その名の通り「無名」で関数定義をします。

main.go
func main() {
   a := func(x, y int) int { return x + y }
   fmt.Println(a(2, 5))  //7
}

また、無名関数にそのまま引数を取ることで、さらに短く描くこともできます。

main.go
func main() {
   fmt.Println(func(x, y int) int { return x + y }(2, 5))  //7
}

これは、関数リテラルを使用した無名関数定義でも、同じように出力します。

関数で関数を返す

無名関数を使用することで、関数で関数を返すことができます。

main.go
func test() func() {
   return func() {
      fmt.Println("出力")
   }
}

func main() {
   a := test()
   a()  //出力
}

このプログラムは、引数も戻り値も持たない関数を戻り値として返した関数を、暗黙的に変数aに代入して出力しています。

関数を引数に取った関数

同じように、関数を引数にとることも可能です。

main.go
func test(a func()) {
   a()
}

func main() {
   test(func() {
      fmt.Println("出力")  //出力
   })
}

このプログラムでは、引数も戻り値も持たない関数を関数testの引数にとり、呼び出したものを、関数mainで無名関数として引数に渡すことで出力されています。

クロージャーを応用したジェネレータ

Goでは、無名関数はクロージャーで、関数閉包のようなものです。通常、関数内で定義されている変数(ローカル変数)は関数の実行が完了したのちに破棄されるのですが、クロージャーと結びついていることで、クロージャーが参照されている限り破棄されることはないのです。このロジックを利用することで、Goにはないジェネレータのような機能を実現することが可能になります。

main.go
func test() func() int {
   a := 0  //クロージャー内から参照されているローカル変数
   return func() int {
      a++
      return a  //ローカル変数(クロージャーに属する変数)を参照している
   }
}

func main() {
   b := test()

   fmt.Println(b())  //1
   fmt.Println(b())  //2
   fmt.Println(b())  //3
   fmt.Println(b())  //4
}

最後に

今回は、関数についてまとめました!オブジェクト指向の機能のないGoでは関数の定義というのが中心的になるのではないでしょうか。

次からは、制御構文についてまとめようと思います!!

参考文献

著者 松尾愛賀
翔泳社 スターティングGo言語

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0