한 눈에 끝내는 고랭 기초
    • 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)
      최종 코드
    비동기 채널과 버퍼
    18 채널(Channel)
    비동기 채널과 버퍼

    이전 강의에서 채널은 고루틴간의 데이터 송/수신을 위해 존재하는 것이기 때문에 채널을 사용하기 위해서는 고루틴을 꼭 사용해야한다고 했습니다. 채널에서는 데이터 송/수신의 역할을 하는 송신자와 수신자가 있습니다. 송신자는 채널에 데이터를 보내는 역할을 하고(채널 <- 데이터), 수신자는 채널로부터 데이터를 받는 역할을 합니다.(<- 채널) 또한 채널을 사용한 송신 루틴은 수신 루틴이 데이터를 받을 때까지, 수신 루틴은 송신 루틴이 데이터를 보낼 때까지 대기합니다. 따라서 채널을 이용해 비동기 프로세스에서 데이터를 원활하게 주고받을 수 있으며, 고루틴간의 흐름을 제어할 수 있는 것입니다. 이렇게 채널은 비동기 프로세스의 기능을 원활하게 해주고 극대화시킵니다. 

    채널을 사용할 때 우리가 간과할 수 있는 치명적인 오류가 발생할 수 있는데 바로 '데드락(Deadlock)'입니다. 데드락은 한국말로 '교착 상태'라는 뜻인데 이것에 관해 설명하자면 컴퓨터 구조론 서적의 한 챕터를 설명하는 것과 마찬가지기 때문에 채널 사용에서 발생하는 상황만 설명하겠습니다. 데드락은 둘 이상의 프로세스(함수)가 서로 가진 한정된 자원을 요청하는 경우 발생하는 것으로, 프로세스가 전진되지 못하고 모든 프로세스가 대기 상태가 되는 것을 말합니다. [출처 : 네이버 지식백과] 채널을 사용할 때는 main() 함수에서 고루틴이 무한 대기 상태가 됐을 때 데드락이 발생합니다. 쉽게 말해서, main() 함수에서 송/수신 채널이 대기 상태가 되면 프로그램이 진행되지 않아 종료되지 않는 것입니다. 


    아래 수신자가 없어 무한 대기로 데드락이 발생하는 코드를 바로 실행해보세요.

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

    위 코드에서 c라는 string형 채널을 생성하고 데이터를 보내고있는데 데이터를 받는 수신자(수신 루틴)가 없기 때문에 값을 수신할 때까지 무한 대기하는 데드락이 발생하는 것입니다. 그래서 송/수신을 위한 고루틴을 만들고 수신자와 송신자의 요건을 충족시키면 데드락 상황이 발생하지 않고 프로그램이 실행됩니다. 


    비동기 채널 버퍼 


    이때, 채널에서 송/수신이 꼭 일대일 대응을 해야하기때문에 좀 번거로운 상황이 생길 수 있습니다. 그래서 이를 중재하는 역할을 하는 '버퍼'라는 것이 있습니다. 송신 루틴에서 수신 루틴으로 데이터를 바로 전달하는 것이 아니라 특정 개수의 버퍼를 만들어 송신자는 버퍼로 데이터를 보내고, 수신자는 버퍼에서 데이터를 가져오게끔 합니다. 쉽게 말해서, 송/수신자를 연결하는 통로 중간에 데이터를 잠깐 저장할 수 있는 공간을 마련하는 것입니다. 버퍼를 만드는 형식은 "make(chan 데이터타입, 버퍼 개수)" 입니다.

    default

    여기서 주의할 점이 있는데 쉽게 기억하는 방법이 있습니다. 송신자와 수신자는 서로 사이가 안좋아 자기가 할 일만 하면 끝이라고 생각하는 것입니다. 따라서 송신 루틴은 수신자가 없어도 버퍼에 보내면 일을 끝내고, 수신 루틴은 일단 값을 받으면 송신 루틴의 일이 끝나든 아니든 자신의 일을 끝냅니다.


    아래 채널 버퍼를 만들어 수신 루틴이 없어도 버퍼에 값을 보내 오류 없이 프로그램이 종료되는 예시 코드를 바로 실행해보세요.

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

    비동기 채널 버퍼에서 고루틴의 대기 조건을 정리해보겠습니다.

    • 송신 루틴은 버퍼가 가득차면 대기합니다.
      • 보내고 할 일을 함. 보낸 순간 버퍼가 가득찼으면 대기, 버퍼에 빈 공간이 생기면 하던 일 마저 끝냄.
    • 수신 루틴은 버퍼에 값이 없으면 대기합니다.(버퍼에 값이 들어올 때까지)


    아래 채널 버퍼링을 이용한 예시 코드를 바로 실행해보세요.

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

    송신자는 수신자가 직접 데이터를 받을때까지 대기하지 않고 버퍼에 값을 보내기만 하면 다음 코드를 실행하기 때문에 훨씬 효율이 높아집니다. 물론 버퍼가 가득 차서 더이상 송신할 수 없을 때는 다음 코드를 실행하지 않고 채널에 묶여버립니다.(무한 대기 상태) 또한 main() 함수의 수신 루틴은 한개 받고 한개를 처리할 필요 없이 버퍼에 값이 있으면 바로바로 꺼내 씁니다. 똑같이 더이상 버퍼에 값이 송신되지 않으면 수신 루틴은 무한 대기 상태가 되고 main() 함수에서는 데드락이 발생합니다. 따라서 송/수신 채널의 개수를 잘 맞춰줘야합니다.


    구름IDE를 사용해 송/수신 채널의 개수를 수정해서 출력 값을 확인하고 결괏값이 어떻게 출력되는지 확인하세요.

    질문하기