Notice
Recent Posts
Recent Comments
Link
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Archives
Today
Total
관리 메뉴

Code Habit

Go ) 함수 본문

카테고리 없음

Go ) 함수

코드베어 2020. 5. 20. 10:21

Go 언어는 다음과 같이 간단하게 함수를 정의하고 호출할 수 있다.

  • func 함수명(){}
func hello() {
    fmt.Println("Hello, world!")
}

func world()
{   // 컴파일 에러
    fmt.Println("world !");
}

func main() {
    hello()
}

Go 언어는 함수 정의를 시작한 줄에서 { (여는 중괄호)가 시작된다. 다음 줄에 작성하면 컴파일 에러가 발생한다.

 

※ Go언어는 함수를 정의할 때 C, C++과 다르게 위치 제약이 없다. 즉 뒤에 정의해도 앞에서 사용할 수 있다.

 

함수에서 매개변수를 받고 값을 리턴하는 방법을 알아보겠다.

  • func 함수명(매개변수명 자료형) 리턴값 자료형 {}
func sum(a int, b int) int {
    return a + b
}

func main() {
    r := sum(1, 2)
    fmt.Println(r) // 3
}

 

Go 언어는 리턴값에 이름을 지정할 수도 있다.

  • func 함수명(매개변수명 자료형) (리턴값 변수명 자료형) {}
func sum(a int, b int) (r int) {
    r = a + b	// 리턴값 변수 r에 값 대입
    return		// 리턴값 변수를 사용할 때는 return 뒤에 변수를 지정하지 않음
}

func main() {
    r := sum(1, 2)
    fmt.Println(r)
}

 

Go 언어는 함수에서 값을 여러 개 리턴할 수 있다.

  • func 함수명(매개변수명 자료형) (리턴값 자료형1, 리턴값 자료형2) { }
func SumAndDiff(a int, b int) (int, int) { // int 형 리턴값이 두 개인 함수 정의
    return a + b, a - b // 리턴할 값 또는 변수를 차례대로 나열
}

func main() {
    sum, diff := SumAndDiff(6, 2) // 변수 두 개에 리턴값 두 개를 대입
    fmt.Println(sum, diff)
    
    _, diff2 := SumAndDiff(8, 3)
    fmt.Println(diff2)
}

여기서 리턴값은 함수에서 지정한 순서대로 리턴된다. 따라서 리턴값을 받을 변수 하나만 지정하면 첫 번째 리턴값만 저장된다. 첫 번째 리턴값을 생략하고 두 번째 리턴값부터 사용하고 싶다면 _(밑줄 문자)를 사용한다.

 

함수의 매개변수 개수가 정해져 있지 않고 유동적으로 변하는 형태를 가변인자라고 한다.

  • func 함수명(매개변수명 ...자료형) 리턴값_자료형 {}
func sum(n ...int) int {
    total := 0
    for _, value := range n {
        total += value
    }
    
    return total
}

func main() {
    r := sum(1, 2, 3, 4 ,5)
    fmt.Println(r) // 15
    
    n := []int{1, 2, 3, 4, 5}
    r = sum(n...) // ...을 사용하여 가변인자에 슬라이스를 바로 넘겨줌
    
    fmt.Println(r)	// 15
}

매개변수의 자료형 앞에 ...을 붙여 가변인자로 지정한다. 여기서 가변인자로 받은 변수는 슬라이스 타입이므로 range키워드를 사용하여 값을 꺼내 사용하면 된다.

 

가변인자는 슬라이스 타입이므로 슬라이스를 바로 넘겨줄 수도 있다. 단 여기서 가변인자 함수는 int형 값만 여러 개 받도록 되어 있고, 슬라이스 자체는 받을 수 없으므로 매개변수에 슬라이스만 넣지 않고 뒤에 ...을 붙인다. ...을 붙이면 슬라이스에 들어 있는 요소를 각각 넘겨준다.

 

Go 언어는 간단하게 함수를 변수에 저장할 수 있다.

  • var 변수명 func(매개변수명 자료형) 리턴값 자료형 = 함수명
func sum(a int, b int) int {
    return a + b
}

func main() {
    var hello func(a int, b int) int = sum  // 함수를 저장하는 변수를 선언하고 함수 대입
    world := sum                            // 변수 선언과 동시에 함수를 바로 대입
    
    fmt.Println(hello(1,2)) // 3: hello 변수에 저장된 sum 함수 호출
    fmt.Println(world(1,2)) // 3: world 변수에 저장된 sum 함수 호출
}

Go 언어는 변수를 선언하고 대입할 때 자동으로 자료형을 추론할 수 있으므로 :=를 사용하면 간단하게 변수에 함수를 저장할 수 있다.

 

변수뿐만 아니라 슬라이스(배열)에도 함수를 간단하게 저장할 수 있다.

  • 슬라이스 = []func(매개변수명 자료형) 리턴값 자료형{함수명1, 함수명2}
func sum(a int, b int) int {
    return a + b
}

func diff(a int, b int) int {
    return a - b
}

func main() {
    f := []func(int, int) int{sum, diff}  // 함수를 저장할 수 있는 슬라이스를 생성한 뒤
                                          // 함수로 초기화
                                            
    fmt.Println(f[0](1,2))  // 3 : 배열의 첫번째 요소로 함수 호출
    fmt.Println(f[1](1,2))  // -1 : 배열의 두 번째 요소로 함수 호출
}

[] 뒤에 매개변수의 자료형과 리턴값의 자료형을 지정해야 하며 {} (중괄호) 안에 대입할 함수명을 나열하면 된다.

 

마찬가지로 맵에도 함수를 간단하게 저장할 수 있다.

  • 맵 := map[키 자료형]func(매개변수명 자료형) 리턴값 자료형("키":함수명}
func sum(a int, b int) int {
    return a + b
}

func diff(a int, b int) int {
    return a - b
}

func main() {
    f:= map[string]func(int, int) int {	// 함수를 저장할 수 있는 맵을 생성한 뒤 
        "sum" : sum,					// 함수로 초기화
        "diff" : diff,
    }
    
    fmt.Println(f["sum"](1, 2))  // 3 : 맵에 sum 키를 지정하여 함수 호출
    fmt.Println(f["diff"](1, 2)) // -1 : 맵에 diff 키를 지정하여 함수 호출
}

 

Go 언어는 JavaScript처럼 함수 안에서 이름이 없는 익명 함수를 정의한 뒤 바로 호출할 수 있다.

  • func(매개변수명 자료형) 리턴값 자료형{}()
func main() {
    func() {	// 함수에 이름이 없음
        fmt.Println("Hello, world!")
    }()
    
    func(s string) {	// 익명 함수를 정의한 뒤
        fmt.Println(s)
    }("Hello, world!")   // 바로 호출
    
    r := func(a int, b int) int {
        return a + b
    }(1, 2)
    
    fmt.Println(r)     // 3
}

// 실행 결과
Hello, world!
Hello, world!
3

익명 함수는 함수를 정의한 뒤 () (괄호)를 사용하여 바로 함수를 호출한다. 이때도 매개변수 및 리턴값을 사용할 수 있다. 이런 익명함수는 코드 양을 줄일 수 있으며 클로저, 지연 호출(defer), 고루틴(go)에서 주로 사용된다.