[go] Go 언어에서 함수형 프로그래밍

Go 언어는 정적 타입의 컴파일 언어로, 주로 시스템 수준의 프로그래밍에 사용되는 언어입니다. Go 언어는 기능적인 프로그래밍 패러다임을 지원하지는 않지만, 몇 가지 기능을 통해 함수형 프로그래밍 스타일을 적용할 수 있습니다.

익명 함수 (Anonymous Functions)

Go 언어는 익명 함수를 지원하여, 함수를 변수에 할당하거나 함수의 인자로 전달할 수 있습니다. 이를 통해 함수를 일급 객체로 취급할 수 있고, 함수를 다른 함수의 반환 값으로 사용할 수 있습니다.

func main() {
    add := func(a, b int) int {
        return a + b
    }

    result := add(3, 4)
    fmt.Println(result) // 출력: 7
}

고계 함수 (Higher-Order Functions)

고계 함수는 함수를 인자로 받거나 함수를 반환하는 함수를 말합니다. Go 언어에서는 클로저(closure)를 활용하여 고계 함수를 구현할 수 있습니다.

func adder() func(int) int {
    sum := 0

    return func(x int) int {
        sum += x
        return sum
    }
}

func main() {
    a := adder()

    fmt.Println(a(1)) // 출력: 1
    fmt.Println(a(2)) // 출력: 3
    fmt.Println(a(3)) // 출력: 6
}

위 예제에서 adder 함수는 func(int) int 타입을 반환하는 함수입니다. 반환된 함수는 클로저로서 sum 변수에 접근하여 값을 누적합니다.

불변성 (Immutability)

Go 언어는 불변성을 강제하지 않습니다. 하지만, 구조체를 사용하여 값이 변경되지 않도록 만들 수 있습니다. 이를 통해 함수형 프로그래밍에서 중요하게 다루는 불변성을 사용할 수 있습니다.

type Point struct {
    X int
    Y int
}

func Move(p Point, dx int, dy int) Point {
    p.X += dx
    p.Y += dy
    return p
}

func main() {
    p := Point{X: 1, Y: 2}
    fmt.Println(p) // 출력: {1 2}

    moved := Move(p, 3, 4)
    fmt.Println(moved) // 출력: {4 6}

    fmt.Println(p) // 출력: {1 2}
}

위 예제에서 Move 함수는 Point 구조체를 인자로 받아 값을 변경한 후 새로운 Point 구조체를 반환합니다. 이렇게 하면 원래의 Point 값을 변경하지 않고 새로운 값으로 이동한 것을 표현할 수 있습니다.

참조 투명성 (Referential Transparency)

참조 투명성은 함수의 결과가 동일한 입력에 대해 항상 같은 값이 나오는 것을 말합니다. Go 언어에서는 일부 함수를 참조 투명한 형태로 구현할 수 있습니다.

func Add(a, b int) int {
    return a + b
}

func main() {
    result := Add(3, 4)
    
    fmt.Println(result) // 출력: 7
}

위 예제에서 Add 함수는 동일한 인자에 대해 항상 같은 결과를 반환하기 때문에 참조 투명한 함수입니다.

결론

Go 언어는 함수형 프로그래밍 언어가 아니지만, 익명 함수, 고계 함수, 불변성, 참조 투명성 등의 기능을 통해 함수형 프로그래밍 스타일을 일부 적용할 수 있습니다. 이러한 기능을 적절히 활용하면 더 모듈화되고 유연한 코드를 작성할 수 있습니다.

참고 자료