プログラミング超入門(９)〜GO言語〜

#関数
関数とは、色々な処理をまとめたもので「同じものを二度書く必要がない」「同じものを他の場面で使用できる」「他の人とも共有できる」など、とても便利です。関数を作ることを「関数を定義する」といいます。GO言語での関数の定義方法は`func 関数名( ){実行したい処理}`**func**を記述し→関数名→(　)`丸括弧に変数名「引数」を入れることで関数に値を渡せますこの引数は関数内で使用することができ、関数内にある数字と引数を(引数＊３)のように計算したりできます。`→{　}波括弧の中には実行したい処理を記述する形です。**関数に引数を渡したり、関数が引数を受け取ったりするわけです。**
##引数の定義
(引数０１,引数０２,引数０３...)のように **,** カンマで区切ると引数を何個でも渡すことができます。`(引数名 データ型)もしくは(　)で省略することもできます`
##戻り値
関数は引数を受け取る一方、実行したい処理結果を返すことができます。式の結果が値になるのと同じように、関数も結果として値を返すのです。慣例的には、関数は値を「戻す」と呼んでいるので、その値を**戻り値**と呼びます。`return`を使うことで戻り値として関数の外へ値を返すことができます。
##関数を呼び出す(関数を使用する)
**Println関数**や**Printf関数**は`標準関数`と呼ばれていて、GO言語にあらかじめ実装されています。前回、変数thenに具体的な数値を割り当てなく、特定の値しか計算出来ていなかったので、プログラムを書き換えて好きな整数を使い処理が行えるようにしてみます。
main関数の外にgetfactor関数を用いて、前回のforswitch.goの割り算プログラムに整数を設定し、処理を行ってみます。getfactor関数はmain関数の外に記述します。main関数の中にgetfactor関数をいれることで好きな整数を入れ同じ処理が行えるようになります。

```getfactor.go
package main

import "fmt"

func getfactor(then int) {
	fmt.Println(then)
	for n := 0; n < then; n++ {
		switch {
		case n == 0:
		case n == 1:
		case then%n == 0:
			then /= n
			fmt.Printf("を%dで割ると、%d\n", n, then)
		default:
		}
	}
	fmt.Println()
}

func main() {
	getfactor(3456)
	getfactor(45678)
	getfactor(567890)
}
```
##ビルドして実行

```
3456
を2で割ると、1728
を3で割ると、576
を4で割ると、144
を6で割ると、24
を8で割ると、3

45678
を2で割ると、22839
を3で割ると、7613
を23で割ると、331

567890
を2で割ると、283945
を5で割ると、56789
を109で割ると、521
```
上記のコードでは、`int型`が使用されていますが、関数は処理だけ行い値は戻していません。`int型`の値を戻すように定義してみます。関数が値を戻す場合、処理の最後に`return`とともに戻り値を書きます。実際に戻す値のデータ型を定義した戻り値の型と一致させ、計算した結果である整数を戻して**main関数**の中でコードを書いてみます。

```averagescore.go
package main

import "fmt"

func averagescore(scores []int) int {
	sum := 0
	for i := 0; i < len(scores); i++ {
		sum += scores[i]
	}
	return sum / len(scores)
}

func main() {
	calscores := []int{92, 56, 87, 73, 46, 68, 90, 28, 69, 41, 82, 66, 51, 79}
	fmt.Printf("%d名による英語の試験結果:\n", len(calscores))
	fmt.Printf("平均点 %d点\n", averagescore(calscores))
}
```

戻り値には変数名をつけません。関数名が戻り値の変数名と同じ役割をしてくれるからです。上記の`averagescore関数`は、引数として渡したスライスが見ている配列の要素の値の平均値を戻すようになています。スライス`calscores`の内容を`averagescore関数`の引数に渡してありますが、引数名と引数に渡す変数名は違っていても同じでも問題ありません。
##ビルドして実行

```
14名による英語の試験結果:
平均点 66点
```
##それぞれの関数の値

```averagescore.go
package main

import "fmt"

func averagescore(scores []int) int {
	sum := 0
	for i := 0; i < len(scores); i++ {
		sum += scores[i]
	}
	return sum / len(scores)
}

func twoscore(a int, b int) int {
	return (a - b) * (a - b)
}

func averagevar(scores []int, avg int) int {
	sum := 0
	for i := 0; i < len(scores); i++ {
		if avg == 0 {
			sum += scores[i]
		} else {
			sum += twoscore(scores[i], avg)
		}
	}
	return sum / len(scores)
}

func twomaxmin(scores []int) (max int, min int) {

	max = scores[0]
	min = scores[0]

	for i := 1; i < len(scores); i++ {
		if max < scores[i] {
			max = scores[i]
		}
		if min > scores[i] {
			min = scores[i]
		}
	}
	return
}

func main() {
	calscores := []int{92, 56, 87, 73, 46, 68, 90, 28, 69, 41, 82, 66, 51, 79}
	fmt.Printf("%d名による英語の試験結果:\n", len(calscores))
	fmt.Printf("平均点 %d点\n", averagescore(calscores))
	fmt.Printf("分散　 %d点\n", averagevar(calscores, averagevar(calscores, 0)))
	max, min := twomaxmin(calscores)
	fmt.Printf("最高点 %d点\n", max)
	fmt.Printf("最低点 %d点\n", min)
}
```
twoscore関数を用いて複数の数値の分散という統計値(それぞれの値と平均値の差の２乗の平均値)を表示させます。２つの引数に与えた値の差の２乗を戻すよう定義します。(a - b)で今回は書きましたが(x - y)でも大丈夫です。

```go
func twoscore(a int, b int) int {
    return (a - b) * (a - b)
}
```
引数avgに0を与えると普通の平均値、avgに平均値を与えると分散を計算するようにaveragevar関数を定義します。分散を計算した時にavgに与える平均値は同じaveragevar関数でavgに0を与えた戻り値です。

```go
func averagevar(scores []int, avg int) int {
    sum := 0
    for i := 0; i < len(scores); i++ {
        if avg == 0 {
            sum += scores[i]
        } else {
            sum += twoscore(scores[i], avg)
        }
    }
    return sum / len(scores)
}
```
averagevar関数を使用して分散を求めるため、引数に与えるために一度averagevar関数を呼び出して求めた平均値でもう一度averagevar関数を呼び出します。

```
fmt.Printf("分散　 %d点\n", averagevar(calscores, averagevar(calscores, 0)))
```
GO言語では、１つの戻り値を複数与える事ができ、スライスを引数に与えるとそのスライスが見ている配列の要素の最大値と最小値を与える関数が定義できます。twomaxmin関数として戻り値に引数のような変数名を与え、関数の中でそれらの変数に値を与えます。関数の最後に`return`と書くと、これらの戻り値が与えられることが自動的に決まります。maxとminに値を与えるにはfor文とlen関数を使って以下のように書きます。

```go
func twomaxmin(scores []int) (max int, min int) {

    max = scores[0]
    min = scores[0]

    for i := 1; i < len(scores); i++ {
        if max < scores[i] {
            max = scores[i]
        }
        if min > scores[i] {
            min = scores[i]
        }
    }
    return
}
```
main関数上ではこのtwomaxmin関数を呼び出し、２つの変数で戻り値を受け取ります。

```
max, min := twomaxmin(calscores)
fmt.Printf("最高点 %d点\n", max)
fmt.Printf("最低点 %d点\n", min)
```
##再ビルドして実行

```
14名による英語の試験結果:
平均点 66点
分散　 355点
最高点 92点
最低点 28点
```

[←前回の記事](https://qiita.com/ume-bar/items/e485a93cbe1b8fce6919)　[次の記事へ→](https://qiita.com/ume-bar/items/844d699b5f1bd2f9448f)