함수 정의
package main
import (
"fmt"
)
func Add(a int, b int) int {
return a + b
}
func main() {
c := Add(3, 6)
fmt.Println(c)
}
함수를 호출하면 생기는 일
함수를 호출할 때 입력하는 값을 argument라고 한다. 아규먼트 혹은 인수라고 한다. 반면 함수가 외부로부터 입력받는 변수를 parameter라고 부른다. 매개변수 혹은 파라미터라고 한다.
함수를 호출하며 입력한 값은 실제 함수에서 보낸 값을 그대로 사용하는 것이 아니라 값을 복사해 사용하게 된다. 위 Add() 함수를 호출하게 되면 매개변수를 선언하고 입력한 인수의 값을 복사한다. 예시에서 a는 3, b는 6을 복사한다. 함수가 종료되면 함수에서 사용한 지역 변수에 접근할 수 없고 return으로 함수 결과가 반환되면서 즉시 종료되어 함수를 호출했던 호출 위치로 명령 포인터가 되돌아가서 수행된다.
명령 포인터란? instruction pointer로 프로그램 카운터라고도 불린다. 다음 명령을 수행할 위치를 나타내는 내부 레지스터를 말한다.
Go 언어에서는 인수는 매개변수로 복사된다. 매개변수와 함수 내에서 선언된 변수는 함수가 종료되면 변수 범위를 벗어나서 접근하지 못한다. 다른 언어는 값전달과 레퍼런스전달 두 가지를 지원하기도 하지만 Go언어는 값전달만 지원한다. 변수 전달이 항상 값의 복사로만 이루어진다. 심플하고 일관적인 언어.
함수의 사용 이유
반복 사용 코드를 묶어 중복 코드를 제거한다.
멀티 반환 함수
함수는 값을 여러 개 반환할 수 있다. 반환값이 여럿일 때는 반환 타입들을 소괄호로 묶어서 표현한다.
package main
import (
"fmt"
)
func Divide(a, b int) (int, bool) { // function declaration
// function definition
if b == 0 {
return 0, false
}
return a / b, true
}
func main() {
c, success := Divide(9, 3)
fmt.Println(c, success)
d, success := Divide(9, 0)
fmt.Println(d, success)
}
Divide() 함수를 정의한다. 이 함수는 int 타입 a, b를 매개변수로 받고 int 타입과 bool 타입을 리턴한다. 매개변수 타입이 같으면 간단히 (a, b int)처럼 한번에 표현할 수 있다.
나눗셈 제수가 0이면 0과 false를 반환하게 만들었다. 제수가 0이 아닐 때는 나눗셈 결과와 true를 반환한다.
변수명을 지정해 반환
함수 선언부에 반환 타입을 적을 때 변수명까지 지정해주면, return문으로 해당 변수를 명시적으로 반환하지 않아도 값을 반환할 수 있다.
반환할 변수에 이름을 지정할 경우 모든 반환 변수에 이름을 지정해야 한다. 모두 지정하거나 지정하지 않거나.
package main
import (
"fmt"
)
func Divide(a, b int) (result int, success bool) { // function declaration
// function definition
if b == 0 {
result = 0
success = false
return
}
result = a / b
success = true
return
}
func main() {
c, success := Divide(9, 3)
fmt.Println(c, success)
d, success := Divide(9, 0)
fmt.Println(d, success)
}
재귀 호출
재귀 호출이란 함수 안에서 자기 자신 함수를 다시 호출하는 것을 말한다.
3부터 1까지 재귀 호출을 이용해서 출력하는 예제
package main
import (
"fmt"
)
func printNo(n int) {
if n == 0 {
return
}
fmt.Println(n)
printNo(n-1)
fmt.Println("After", n)
}
func main() {
printNo(3)
}
해당 함수는 n이 0일 때 종료되는 재귀함수이다. 재귀 호출을 사용할 때는 항상 탈출 조건을 정해야한다. 재귀 호출이 종료되는 시점을 명확히 하지 않으면 재귀 호출이 무한히 반복되어 프로그램이 비정상 종료된다.