backend-interview-guide

Go 언어 (Golang) 기본 개념과 활용

목차


Go 언어란?

Go 언어(Golang)는 Google에서 개발한 오픈 소스 프로그래밍 언어로, 간결한 문법과 뛰어난 성능, 동시성 처리 기능을 제공합니다.


Go 언어의 주요 특징

  1. 간결하고 읽기 쉬운 문법

    • 복잡한 문법 없이, 직관적인 코드 작성 가능.
    • 포인터, 구조체 등 시스템 프로그래밍 요소를 제공하면서도, 높은 가독성을 유지.
  2. 강력한 동시성 지원

    • GoroutinesChannels를 통해 경량 동시성 처리.
    • 수백만 개의 경량 스레드를 처리 가능.
  3. 정적 타입 언어

    • 컴파일 타임에 타입 검사를 수행하여 안정성을 보장.
  4. 컴파일 속도

    • Go는 빠른 컴파일 속도를 제공하며, 대규모 애플리케이션에서도 효과적.
  5. 배포 편의성

    • 단일 바이너리로 컴파일되어 외부 의존성 없이 실행 가능.
  6. 풍부한 표준 라이브러리

    • HTTP 서버, 파일 처리, 암호화 등 강력한 내장 기능 제공.

Go의 동시성 처리

Go의 동시성은 Goroutines와 Channels를 기반으로 효율적이고 안전하게 구현됩니다. Go의 동시성 모델은 복잡한 멀티스레드 프로그래밍보다 단순하며, 적은 코드로 고성능을 달성할 수 있습니다. 그러나 동시성을 활용할 때는 Deadlock, Race Condition, Goroutine 누수와 같은 문제를 방지하기 위한 적절한 설계가 필요합니다.

동시성과 병렬성의 차이

Go의 동시성 모델은 작업 간의 협력적인 실행(동시성)을 중점적으로 다루며, 필요에 따라 병렬로 실행될 수 있도록 지원합니다.

Goroutines

Goroutine은 Go의 경량 스레드로, 동시 작업을 효율적으로 처리합니다.

Goroutines의 특징

Goroutine 생성

Goroutine은 함수 앞에 go 키워드를 붙여 실행합니다.

package main

import (
	"fmt"
	"time"
)

func printMessage(message string) {
	for i := 0; i < 5; i++ {
		fmt.Println(message)
		time.Sleep(500 * time.Millisecond)
	}
}

func main() {
	go printMessage("Goroutine 1")
	go printMessage("Goroutine 2")
	time.Sleep(3 * time.Second)
	fmt.Println("Main function finished")
}

실행 결과:

Goroutine 1
Goroutine 2
Goroutine 1
Goroutine 2
...
Main function finished

Channels

Channel이란?

Channel은 Goroutine 간 데이터를 안전하게 교환할 수 있는 메커니즘입니다. Channel은 데이터 전송과 수신을 동기화하여 공유 데이터에 대한 경쟁 상태를 방지합니다.

Channel 생성

ch := make(chan int) // 정수를 전달하는 Unbuffered Channel 생성

데이터 전송과 수신

go func() {
	ch <- 42 // 데이터를 Channel에 전송
}()

value := <-ch // Channel에서 데이터 수신
fmt.Println(value) // 42 출력

Buffered와 Unbuffered Channel

Select 문

Select 문은 여러 Channel의 상태를 동시에 감시하여, 준비된 Channel의 작업을 처리합니다.

package main

import (
	"fmt"
	"time"
)

func main() {
	ch1 := make(chan string)
	ch2 := make(chan string)

	go func() {
		time.Sleep(1 * time.Second)
		ch1 <- "Message from Channel 1"
	}()

	go func() {
		time.Sleep(2 * time.Second)
		ch2 <- "Message from Channel 2"
	}()

	for i := 0; i < 2; i++ {
		select {
		case msg1 := <-ch1:
			fmt.Println(msg1)
		case msg2 := <-ch2:
			fmt.Println(msg2)
		}
	}
}

주의사항과 한계

모든 Goroutine이 Channel에서 대기 상태에 빠지면 발생. 해결 방법: Channel의 크기, 송수신 타이밍을 적절히 설계.

여러 Goroutine이 동시에 동일한 데이터를 수정할 경우 발생. 해결 방법: sync.Mutex와 같은 동기화 메커니즘 사용.

종료되지 않은 Goroutine이 메모리를 차지한 상태로 남아 있을 수 있음. 해결 방법: Context 또는 Done Channel을 사용해 종료 신호 전달.


Go의 주요 활용 사례


Go 사용 시 주의사항


결론

Go 언어는 간결한 문법, 높은 성능, 동시성 지원으로 현대적인 시스템 프로그래밍 및 클라우드 기반 개발에 최적화된 언어입니다. 특히, 클라우드 네이티브 및 대규모 서버 개발을 위해 설계된 Go는 빠른 컴파일 속도와 쉬운 배포로 개발 생산성을 크게 향상시킬 수 있습니다.