Go言語-関数

# 関数
プログラミング基本からGoの理解を文字におこして行こうと思います！

### 関数とは
```go
var input string
fmt.Println("次の単語を入力してください:go")
fmt.Scan(&input)
fmt.Printf("%sと入力されました", input)
```
関数（かんすう）とは、「いくつかの処理をまとめたもの」
処理を関数にまとめると、何度でも使える

上記のコードをask関数にまとめる

### 関数の定義
```go
func ask() {
  var input string
  fmt.Println("次の単語を入力してください:go")
  fmt.Scan(&input)
  fmt.Printf("%sと入力されました", input)
}
```
関数は、「func 関数名()」と書く
「{ }」の中にまとめたい処理を書くことで関数を用意することができる

### 関数の呼び出し
```go
func main() {  //ask関数を呼び出す
  ask()
}
func ask() {
  var input string
  fmt.Println("次の単語を入力してください:go")
  fmt.Scan(&input)
  fmt.Printf("%sと入力されました", input)
}
```
関数を定義しただけでは、その中の処理は実行されない
「関数名()」と書くことで関数の中の処理を実行できる

### 関数を複数回呼び出す
```go
func main() { 
  ask()  
  ask()  //複数回呼びだせる
}
func ask() {
  var input string
  fmt.Println("次の単語を入力してください:Go")
  fmt.Scan(&input)
  fmt.Printf("%sと入力されました", input)
}

//コンソール
//次の単語を入力してください:go 
//go(コンソールで入力)　　　　　　　　　　　 
//goと入力されました

//次の単語を入力してください:go 
//go(コンソールで入力)　　　　　　　　　　　 
//goと入力されました
```
1度定義すれば同様の処理を何度でも実行できるのが関数のメリット

### 関数に値を渡す
```go
func main() { 
  ask("go")  
}
```
関数を呼び出す際に「()」の中に値を書くことで、値を渡すことができる
この値のことを引数という

### 引数を受け取る
```go
func main() { 
  ask("go")  //Goを引数としてquestionに渡している
}

func ask(question string) {  //question→変数名
...
```
渡した値を使うためには、受け取るための変数を用意する必要がある
文字列"cat"をstring型の変数questionで受け取っている

### 引数を使う
```go
func main() { 
  ask("go")    //goを引数としてquestionに渡している
  ask("ruby")  //rubyを引数としてquestionに渡している
}

func ask(question string) {
...
  fmt.Printf("次の単語を入力してください: %s\n", question)

//コンソール
//次の単語を入力してください:go 
...

//次の単語を入力してください:ruby 
...
```
渡された値は受け取った変数名を用いて使うことができる
渡す値を変えることで問題文も変えられる

### 変数の値を渡す
```go
func main() { 
  text := "Go"
  ask(text)

func ask(question string) {
...
  fmt.Printf("次の単語を入力してください: %s\n", question)
}

//コンソール
//次の単語を入力してください:go 
...
```
関数には変数の値を引数として渡すこともできる
変数textを引数として、ask関数の変数questionに渡している

### 複数の引数の渡し方
```go
func main() { 
  ask(1,"go")
  ask(2,"ruby")
  ask(3,"python")
}

func ask(number int, question string) {
  fmt.Printf("[質問%d]次の単語を入力してください: %s\n", number, question)
}

//コンソール
//[質問1]次の単語を入力してください:go
//[質問2]次の単語を入力してください:ruby
//[質問3]次の単語を入力してください:python
```
複数の引数を使うとき、渡す順番に注意
ask関数の引数の順が(問題番号, 問題文)となっている

### 戻り値とは
```go
func ask(number int, question string) int {
  fmt.Printf("[質問%d]次の単語を入力してください: %s\n", number, question)
...
  return 10  //ask関数の戻り値
```
戻り値（もどりち）を使うことで呼び出し元に値を返すことが出来る

ask関数が「1」「go」を受け取り、結果の「10」を呼び出し元に返している
戻り値にあたるのがこの「10」
1行目のintは戻り値の型

### 戻り値の受け取り方
```go
func main() {
  totalScore := ask(1, "go")  //ask関数の戻り値は10
  fmt.Println("スコア", totalScore)
}

func ask(number int, question string)int {
...
 return 10

//コンソール
//[質問1]次の単語を入力してください:go
//スコア 10
```
関数の戻り値は変数に代入するなどして受け取ることができる
ask関数を呼び出して返ってきた戻り値10を変数totalScoreに代入

### 戻り値を計算
```go
func main() {
  totalScore := ask(1, "go")
  totalScore += ask(2, "ruby")
  totalScore += ask(3, "python")
  fmt.Println("スコア", totalScore)
}

func ask(number int, question string)int {
...
 return 10
```
「+=」を使用することで、ask関数の戻り値をそのまま足すことができる

### 正解,不正解の分岐
```go
func ask(number int, question string)int {
  fmt.Scan(&input)
  if question == input {
    fmt.Println("正解")
  }else{
    fmt.Prantln("不正解")
  }
}
```
正解や不正解を判断する条件分岐
出題された問題文と入力された値が同じかどうかで判断

### 戻り値を返す
```go
func main() {
  totalScore := ask(1,"go")
  totalScore += ask(2,"ruby")
  totalScore += ask(3,"python")
  fmt.println("スコア",totalScore)
}

func ask(number int, question string)int {
  if question == input {
    fmt.Println("正解")
    return 10
  }else{
    fmt.Println("不正解")
    return 0
  }
```
正解のとき、returnで10を返す
不正解のとき、returnで0を返す
戻された値をmain関数のtotalScoreに足す

### 関数に値を渡すときの注意点
```go
func main() {
  totalScore := 0
  ask(1,"go")
  ask(2,"ruby")
  ask(3,"python")
  fmt.Println("スコア",totalScore)
}

func ask(number int, question string) {
  if question == input {
    fmt.Println("正解")
    totalScore += 10  //ask関数内からmain関数のtotalScoreに直接足そうとするとエラー
  }
```
戻り値を使わず、main関数の中で定義された変数totalScoreを
ask関数の中で使おうとしてもできない

### 変数のスコープ
```go
func main() {
  totalScore := 0

//変数totalScoreが使用できる範囲(スコープ内)

}

func ask(number int, question string) {

//変数totalScoreが使用できない範囲(スコープ外)

  }
```
main関数の中で定義された変数totalScoreは、main関数の中でしか使えないから
変数には使える範囲があり、その範囲を変数のスコープと呼ぶ

スコープはとても重要です

### スコアを引数で渡す
```go
func main() {
  totalScore := 0
  ask(1,"go",totalScore)
...
  fmt.Println("スコア",totalScore)
}
...
func ask(number int, question string, totalScore int) {
...
  if question == input {
    fmt.Println("正解")
    totalScore += 10
...
  }
}
```
エラーは発生しないが、正解してもスコアが加算されない

### 同じ名前の変数
```go
func main() {
  totalScore := 0
  //main関数の変数 totalScoreのスコープ
}
func ask(number int, question string, totalScore int) {
  totalScore += 10
  //ask関数の引数 totalScoreのスコープ
}
```

main関数で使用しているtotalScoreと
ask関数で使用しているtotalScoreはスコープが違うため
同じ名前だが、別の変数

#### 値のコピー

main関数からask関数へ変数を渡しているように見えるが
実際は変数totalScoreの値をコピーしてask関数に渡している
よって、ask関数のtotalScoreに値を足しても、もとの値は変わらない