[Go] 함수 리터럴

Hoplin·2023년 8월 17일
0
post-thumbnail

함수 리터럴

함수 리터럴은 일종의 익명함수이다(즉 이름이 없다). 다른 말로는 람다함수라고 불리기도 한다(go언어에서). Go언어에서 함수 리터럴을 선언하는 방식은 아래와 같다

변수 := func(매개변수) 반환값 {}

예시는 아래와 같다.

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

//결과
3

함수 리터럴은 JavaScript처럼 즉시실행 함수로 활용할 수 도 있다.

func main() {
	func(a, b int) {
		fmt.Println(a + b)
	}(1, 2)
}

캡쳐

함수 리터럴은 상위 스코프의 변수도 활용할 수 있다.다만 주의할 점이 있다. 함수 리터럴 외부 변수를 함수 리터럴 내부로 가져오는것을 캡쳐라고 한다. 캡쳐는 값을 복사하는것이 아닌, 참조를 하는 형태이다. 값을 복사 방식으로 가져오는 JavaScript와의 차이점이다.

function test() {
  const arr1 = new Array()
  for (let i = 0; i < 5; i++) {
    arr1.push(() => {
      console.log("Print : ", i)
    })
  }

  arr1.map((x) => x())
}

test()

// 결과
Print :  0
Print :  1
Print :  2
Print :  3
Print :  4

동일한 코드를 go언어로 바꾸면 아래와 같은 결과가 나오게 된다.

func main() {
	functions := make([]func(), 5)
	for i := 0; i < 5; i++ {
		functions[i] = func() {
			fmt.Println("Print : ", i)
		}
	}

	for _, v := range functions {
		v()
	}
}

//결과
Print :  5
Print :  5
Print :  5
Print :  5
Print :  5

이를 방지하기 위해서는 각각의 i값을 변수에 복사한 후 각각의 함수 리터럴에서 복사한 변수를 캡쳐하도록 변경해주어야한다.

func main() {
	functions := make([]func(), 5)
	for i := 0; i < 5; i++ {
		t := i // i값을 복사
		functions[i] = func() {
			fmt.Println("Print : ", t) // 순회시 캡쳐된 i값이 복사된 t변수를 캡쳐
		}
	}

	for _, v := range functions {
		v()
	}
}

//결과
Print :  0
Print :  1
Print :  2
Print :  3
Print :  4
profile
더 나은 내일을 위해 오늘의 중괄호를 엽니다

0개의 댓글