한 눈에 끝내는 고랭 기초
    • 01
      시작하기에 앞서
    • 강의대상
      Go란?
      실습 환경 구축 - 구름IDE
      Hello goorm! 출력해보기
    • 02
      변수와 상수
    • 콘솔 출력 함수의 기본
      변수의 선언과 초기화
      상수의 선언과 초기화
      간단한 덧셈
      잘못된 신상정보
    • 03
      연산자
    • 연산자 종류
      연산자 우선순위
      콘솔 입력 함수의 기본
      간단한 덧셈과 곱셈
      몫과 나머지
    • 04
      자료형
    • 자료형의 종류와 특징
      문자열의 표현
      자료형의 변환
      강제 형 변환
    • 05
      콘솔 출력과 입력 함수
    • 콘솔 출력 함수(Print)
      콘솔 입력 함수(Scan)
      정돈된 표
      신상정보 입력과 출력
    • 06
      반복문 - for
    • 오로지 for
      구구단
      빛나는 이등변삼각형
    • 07
      조건문 - if/else
    • 조건에 따른 실행과 흐름 분기
      7과 9의 배수
      두 수의 차
    • 08
      분기문 - switch
    • swich문에 의한 선택적 실행
      안좋은 계산기
    • 09
      제어문
    • break, continue, goto문
      구구단2
      두 수를 더하면 99
    • 10
      컬렉션
    • 배열(Array)
      슬라이스(Slice)
      맵(Map)
      역행렬
      가장 긴 이름
      중간고사 평균 점수
    • 11
      함수
    • Go언어에서의 함수
      전역변수와 지역변수
      매개변수
      반환값(리턴값)
      익명 함수
      오름차순 정렬
      아이패드를 사주는 조건
      역학적 에너지
    • 12
      클로저
    • 외부 변수 접근 : 클로저
      동전 정리
    • 13
      구조체와 메소드
    • 구조체
      메소드
      성적 저장 프로그램
      역학적 에너지2
    • 14
      인터페이스(interface)
    • 메소드의 집합 인터페이스
      직육면체와 원기둥
    • 15
      defer와 panic()
    • 지연 처리 defer
      종료하는 panic(), 복구하는 recover()
      엘리베이터
      중간고사 평균 점수2
    • 16
      에러 처리
    • 에러 처리의 기본
      에러 출력 및 처리
      중간고사 평균 점수3
    • 17
      고루틴(Goroutine)
    • 비동기 프로세스의 기본
      고루틴의 활용
      고루틴 실습
    • 18
      채널(Channel)
    • 고루틴의 데이터 통로 : 채널
      비동기 채널과 버퍼
      동기 채널
      채널 닫기
      송신 전용, 수신 전용 채널
      채널 select문
      고루틴 실습2
      메시지 전송
      동기 채널 실습
      비동기 채널 실습
    • 19
      패키지(package)
    • 패키지의 개념
    • 20
      실전 프로젝트 - 마일리지 상점
    • 프로젝트를 시작하기 앞서
      실습모드에서 실습
      마일리지 상점의 주요 기능
      필수 구조체와 매인 메뉴
      잔여 수량, 잔여 포인트 구현
    • 21
      실전 프로젝트 - 주문하기, 장바구니 담기
    • 구매 구현(1)
      구매 구현(2)
      장바구니에 담기
      장바구니 확인(1)
      장바구니 확인(2)
    • 22
      실전 프로젝트 - 고루틴으로 배송하기
    • 배송 상태 확인(1)
      배송 상태 확인(2)
      배송 상태 확인(3)
      최종 코드
    익명 함수
    11 함수
    익명 함수

    지금까지 Go언어에서 쓰이는 함수의 여러 특징들을 배웠습니다.  그중에서도 이번 강의에서 배우는 '익명 함수'는 가장 독특합니다. 익명 함수는 단어에서도 알 수 있듯이 '이름이 없는 함수'입니다. 함수의 이름을 아무렇게나 막 붙이는 경우는 없기 때문에 함수의 이름은 상징적이고 가독성에 있어 중요한 역할을 합니다. 예를 들어, 숫자를  더하는 기능을 하는 함수는 "add"라고 이름을 붙일 수 있습니다. 그렇다면 아이러니하게 '왜 익명 함수라는 것이 있습니까?'라는 의문점이 생길 수 있습니다.

    코드를 작성할 때 아무런 규칙 없이 마구잡이로 작성하는 것보다 코드의 기능별로 '함수화'하는 것이 굉장히 중요하다고 배웠습니다. 그런데 함수들을 만드는 것에 단점이 있는데 바로 '프로그램 속도 저하'입니다. 왜냐하면

    • 함수 선언 자체가 프로그래밍 전역으로 초기화되면서 메모리를 잡아먹기 때문입니다.
    • 기능을 수행할 때마다 함수를 찾아서 호출해야하기 때문입니다.

    그래서 이러한 단점을 보완하기 위해 '익명 함수'가 필요하게 된 것입니다. 우선 기본적인 형태와 용법을 확인하고 알아보겠습니다.


    아래 코드를 바로 실행해보세요.

    go
    실행 결과를 확인해보세요!

    우선 기본적인 형태에 있어서 눈에 띄는 것이 두 가지가 있습니다.

    1. 함수의 이름만 없고 그 외에 형태는 동일합니다.
    2. 함수의 블록 마지막 브레이스(}) 뒤에 괄호(())를 사용해 함수를 바로 호출합니다. 이때, 괄호 안에 매개변수를 넣을 수 있습니다.

    위 예시 코드에서 확인할 수 있는 익명 함수의 가장 큰 특징은 그 자리에서 만들고 그 자리에서 바로 실행하는 것입니다.  main 함수 밖에 선언하고 필요할 때 불러오는 선언 함수와는 다르게 가벼운 느낌이 들지 않나요? 익명 함수는 함수의 '기능적인 요소'만 쏙 빼와서 어디서든 가볍게 활용하기 위해 사용하는 것입니다. 필요한 부분에서 어디서든 효율적으로 사용이 가능합니다.

    선언 함수는 반환 값을 변수에 초기화함으로써 변수에 바로 할당이 가능합니다. 익명 함수도 똑같은 기능을 하는데, 여기서 차이점은 변수에 초기화한 익명 함수는 변수 이름을 함수의 이름처럼 사용할 수 있다는 것입니다.


    아래 코드를 바로 실행해보세요.

    go
    실행 결과를 확인해보세요!

    위 코드는 같은 기능을 하는 선언 함수인 addDeclared와 익명 함수를 할당 받은 변수인 addAnonymous가 있습니다. 선언 함수에 매개변수를 전달해 함수를 호출하는 것과 동일하게 익명 함수를 할당 받은 변수에 매개변수를 전달해서 사용할 수 있는 것을 확인했습니다.

    그리고 선언 함수와 익명 함수는 프로그램 내부적으로 읽는 순서가 다릅니다. 선언 함수는 프로그램이 시작됨과 동시에 모두 읽습니다. 하지만 익명 함수는 위 예시들처럼 그 자리에서 실행되기 때문에 해당 함수가 실행되는 곳에서 읽습니다. 즉, 선언 함수보다 익명 함수가 나중에 읽힙니다. 이러한 개념은 전역변수와 지역변수에서 배웠습니다. 같은 이름의 전역변수는 해당 흐름에 있는 지역변수에게 가려지는 것과 같은 개념입니다.


    아래 코드를 바로 실행해보세요.

    go
    실행 결과를 확인해보세요!

    일급 함수(First-Class Function)


    지금까지 Go언어에서의 함수 자체의 특징, 매개변수의 특징, 반환값의 특징을 배웠습니다. 이런 특징들은 "함수는 이렇게 좋은 성능을 가지고 있다."라고 말하는 것 같았습니다. 하지만 무조건적으로 함수를 선언하는 것은 효율적이지 않다는 것을 배웠고, 이에 따라 함수의 핵심 기능만 유연하게 사용할 수 있는 '익명 함수'에 대해 알아봤습니다. 그런데 익명 함수의 사용은 Go언어에서의 함수가 '일급 함수'이기 때문에 가능한 것입니다.

    일급 함수라는 의미는 함수를 기본 타입과 동일하게 사용할 수 있어 함수 자체를 다른 함수의 매개변수로 전달하거나 다른 함수의 반환 값으로 사용될 수 있다는 것입니다. 따라서 함수는 다른 타입들과 비교했을 때 높은 수준의 용법이 아니라 같은 객체로서 사용될 수 있습니다.


    아래 함수를 반환하고 매개변수로 사용하는 예시 코드를 바로 실행해보세요.

    go
    실행 결과를 확인해보세요!

    위 코드는 헷갈릴 수 있으니 천천히 살펴봐야합니다. 여태껏 우리는 매개변수로서 직관적으로 '변수'라고 생각하는 것을 전달했습니다. 우리의 직관으로는 함수 자체는 매개변수의 역할을 할 수 없다고 느낍니다. 하지만 Go언어에서의 함수는 일급 함수이기 때문에 매개변수로 사용할 수 있고, 변수에 초기화 할 수 있습니다. 함수가 함수의 반환 값으로 사용되는 경우는 '클로저' 챕터에서 배울 것입니다.

    위 코드에는 총 3개의 함수가 있습니다.

    • multi라는 변수에 할당된 두 수를 곱하는 익명 함수
    • 따로 선언하지 않고 전달 인자 자리에 만들어진 두 수를 더하는 익명함수
    • 전달 받은 매개변수를 전달받은 함수의 기능으로 계산하는 calc 함수

    핵심 기능을 하는 calc 함수는 두번 호출되는데 첫 번째는 multi라는 익명함수를 전달받아 10과 20을 곱하고, 두 번째는 두 수를 더하는 익명 함수 자체를 전달받아 10과 20을 더합니다. 

    눈여겨봐야할 점은 clac 함수의 '매개변수형'입니다. 매개변수형으로 '함수형'을 선언했습니다. 전달 받는 함수인 multi 함수와 두 수를 더하는 익명 함수 둘 다 매개변수가 두 개고 int 형입니다. 그리고 반환형도 int입니다.  따라서 func calc(f func(int, int) int, a int, b int) int { 형식으로 입력했습니다. 함수를 매개변수형으로 사용할 때는 "매개변수함수이름 func(전달받는함수의매개변수형) 전달받는함수의반환형" 형태로 선언합니다. 매개변수형으로 함수를 쓸 때는 꼭 전달받는 함수의 형태에 주의해야합니다.


    type문을 사용한 함수 원형 정의


    위에서 Go언어에서의 함수는 일급 함수임을 증명하기 위해 '함수형'을 '매개변수형'으로 선언하는 형태를 예시 코드와 함께 살펴봤습니다. 그런데 확실히 깔끔하지 못하다는 느낌이 듭니다. 왜냐하면 int, float32와 같은 형들은 그 자체에 의미를 가지고 있고 쉽게 알아볼 수 있는 한 단어지만, 함수형을 표현할 때는 전달받는 함수의 형태에 따라 형태가 달라질 뿐더러 길고 가독성이 떨어집니다. 예를 들어, 전달 받는 함수가 매개변수가 5개고 반환형이 6개일 때는 그 함수를 매개변수로 사용할 때마다 그만큼을 명시해야 합니다. 따라서 이를 극복하기 위해 Go언어에서는 'type'문을 사용해 함수의 원형을 정의하고 사용자가 정의한 이름을 형으로써 사용합니다.  이러한 사용자의 Custom Type은 C언어의 '구조체' 개념과 유사합니다. 


    위 코드를 수정해 type문을 활용해보겠습니다. 아래 코드를 바로 실행해보세요.

    go
    실행 결과를 확인해보세요!

    type문을 이용해 두 문자열을 복제하는 함수형을 calculatorStr로 정의하고, 두 정수를 합하는 함수형을 calculatorNum으로 정의했습니다. 따라서 두 함수를 전달받을 때 일일이 길게 선언하지 않고, 사용자가 정의한 형태만 명시할 수 있습니다. 코드가 훨씬 간결하고 깔끔해졌음을 확인할 수 있습니다.

    이처럼 프로그래밍은 끊임없이 효율성을 높이는 작업입니다. type문은 함수 원형 정의 뿐만이 아니라 구조체, 인터페이스 등을 정의하기 위해 사용됩니다. 구조체와 인터페이스를 배우기 전에 미리 type문을 배웠다고 생각하세요. 

    익명 함수는 가볍게 사용할 수 있고 선언 함수의 쓰임새를 확장했습니다. 이를 이용해 익명 함수는 뒤에 나오는 챕터인 '클로저', 'defer', 'Go루틴'에서 많이 다루게됩니다.

    질문하기