Connecting

Go 언어 클로저 / 재귀 / 지연호출 본문

Go 언어

Go 언어 클로저 / 재귀 / 지연호출

팬도라 2020. 7. 14. 14:56
반응형

클로저 / 재귀 / 지연호출

클로저 사용하기

Go 언어에서의 클로저란 익명 함수(Anonymous functions)와 비슷한 개념으로 이름 없이 한줄로 함수를 정의하고 싶을때 유용합니다. 이를 통해 함수 안에서 함수를 선언 및 정의할 수 있고, 바깥쪽 함수에 선언된 변수에도 접근할 수도 있습니다.

아래 예제를 통해 클로저 사용 예제를 확인하시길 바랍니다.

package main
import f "fmt"

func main() {

    f.Println("클로저")

    sum := func(a int, b int) int {
        return a + b
    }
    result := sum(1, 2)
    f.Println(result)

    f.Println("-----------------")

    cal := voltage()
    f.Println(cal(2, 4))
    f.Println(cal(5, 2))
    f.Println(cal(10, 5))

}

func voltage() func(i int, r int) int {

    return func(i int, r int) int {
        return i * r
    }

}

위의 예제를 살펴보면 클로저를 통해 함수를 호출하고 이를 통해 값을 반환합니다. 하지만 위의 예제만 가지고는 왜 클로저를 사용하는지 알 수 없습니다. 복잡해 보이는 클로저를 사용하는 이유는 다음과 같습니다.

지역변수는 함수 호출이 끝나면 소멸됩니다. 하지만 클로저를 사용하면, 지역변수는 소멸되지 않고 호출할 때마다 지속적으로 사용할 수 있기 때문에 함수를 선언했을때의 환경을 유지할 수 있습니다. 이를 통해 프로그래밍의 흐름을 제어할 수 있으므로, 함수형 프로그래밍 언어의 큰 장점이라고 할 수 있습니다.

다음 예제를 통해 확인해보세요.

package main
import f "fmt"

func main() {

    nextInt := intSeq()
    f.Println(nextInt())
    f.Println(nextInt())
    f.Println(nextInt())

    newInts := intSeq()
    f.Println(newInts())

}

func intSeq() func() int {

    i := 0
    return func() int {
        i += 1
        return i
    }

}

재귀 사용하기

함수가 계속해서 자기 자신을 호출해서 사용하는 것을 재귀함수하고 합니다. 재귀함수 자체는 호출이 지속적으로 반복적으로 이루어지기 때문에 성능이 떨어진다는 단점이 있지만 알고리즘 자체가 재귀적으로 표현하기 자연스러울 때 혹은 변수 사용을 줄여줄때 많이 사용합니다. 따라서 재귀 함수를 사용할 때는 이득과 이로 인해 발생하는 성능하락을 고려하여 사용하는 것이 좋습니다. 아래는 재귀함수를 이용한 간단한 예제입니다.

package main
import f "fmt"

func main() {

    f.Println("재귀 함수")
    f.Println(fact(5))

}

func fact(n int) int {

    if n == 0 {
        return 1
    }
    return n * fact(n-1)

}

지연호출이란?

Go 언어에서 지연호출이란 현재 함수가 끝나기 직전에 실행되는 것을 뜻합니다. 다음 예제를 실행해 보면 쉽게 감을 잡을 수 있습니다.

package main 
import f "fmt"

func hello(a int){ 
  f.Println("Go " , a) 
} 

func main(){ 

  defer hello(4)
  hello(1) 
  hello(2) 
  hello(3) 

}
package main 
import f "fmt"

func main(){ 

    for i:=0; i<5; i++{
      defer f.Printf("%d ", i) 
  } 

}

지연 호출을 사용하면 추후 파일을 읽고 쓰는 작업을 진행할 때, 파일 스트림을 나중에 닫아야 하는 여러 상황에서 유용하게 사용될 수 있기 때문에 흐름에 따른 분기 실행에 익숙해질 필요가 있습니다. 다음 예제는 지연호출을 사용하여 다양한 어떻게 동작하는지 확인해보도록 하겠습니다. 코드를 먼저 실행하기 전에 어떠한 형식으로 값이 출력될지 확인해 보시길 바랍니다.

package main
import f "fmt"

func main() {

    f.Println("지연 호출")
    name()

    array := []int{1, 2, 3, 4, 5}

    for _, value := range array {
        defer f.Println(value)
    }
}

func name() {
    defer func() {
        f.Println("lee")
    }()

    func() {
        f.Println("seongwon")
    }()
}
Comments