1. Go 언어란?
Go 언어는 구글에서 개발한 프로그래밍 언어입니다. 2009년에 처음 발표되었고, 2012년에 공식적으로 Release 되었습니다. 주로 서버 개발, 클라우드 인프라 구축, DevOps 툴 제작을 할 때 사용되고 있습니다. 문법이 간결하고 실행 속도가 빠르며, 병렬처리(concurrency
)가 강력하다는 특징이 있습니다.
1.1. Go 언어의 장점
1.1.1. 간결한 문법과 낮은 러닝 커브
간결한 문법을 자랑하는 Python과 같이 Go 언어도 간결한 문법을 가지고 있습니다. 세미콜론(;) 생략 가능하며, 클래스/상속과 같이 복잡한 구조 없이도 필요한 기능을 구현할 수 있습니다. 간결한 문법으로 코드의 가독성도 높아지고 쉽게 배울 수 있는 장점이 있습니다. (물론 러닝 커브가 낮다는 것은 상대적인 것이기 때문에 누군가한테는 쉬울 수도 있고, 어려울 수도 있습니다.)
다음 예시 코드를 보면 Java와 같이 다른 언어에 비해 간결한 문법을 지니고 있음을 알 수 있습니다.
package main
import "fmt"
func main() {
name := "bluemiv"
fmt.Println("안녕하세요,", name)
}

위 코드처럼 python과 같이 Println
으로 출력이 가능하며, 변수 선언도 :=
으로 간단하게 할 수 있습니다. 이런 간결함은 가독성 뿐만 아니라 생산성을 높이는 데 큰 도움이 됩니다.
1.1.2. 강력한 병행처리(concurrency)
Go는 고루틴(goroutine
)이라는 경량 스레드를 제공합니다. goroutine은 수천 개가 동시에 실행될 수 있기 때문에 병행처리(concurrency
)가 뛰어나며, 앞에서 말한 것과 같이 경량 스레드를 제공하여 매우 적은 메모리를 사용합니다.
goroutine
은 Go를 사용하는 이유 중 하나라고 할 수 있습니다.
package main
import (
"fmt"
"time"
)
func sendMessage(name string) {
for i := 0; i < 5; i++ {
fmt.Println(name, "메시지 전송 중 입니다...")
time.Sleep(1 * time.Second)
}
}
func main() {
go sendMessage("User1")
go sendMessage("User2")
time.Sleep(6 * time.Second)
fmt.Println("모든 메시지 전송 완료!")
}

1.1.3. 매우 빠른 속도의 빌드 속도가 매우 빠름
Go는 컴파일 언어이지만 빌드 속도가 매우 빠릅니다. 이는 대규모 시스템에서도 개발 및 테스트 사이클을 빠르게 반복할 수 있게 도와준다.
go의 컴파일 속도가 빠른 이유
- 간단한 의존성 관리
- 컴파일 속도에 최적화된 컴파일러
- 패키지 단위 캐싱
- 헤더 파일 없음
- 정적 링크 기반 방식을 사용
자세한 내용은 "Go는 왜 컴파일 속도가 빠를까?" 를 참고해주세요.
1.1.4. 단일 바이너리로 배포 가능
Go는 모든 의존성을 포함한 단일 실행 파일로 패키징되기 때문에 배포가 매우 간편하고, 복잡한 환경 설정 없이도 다른 시스템에서 바로 실행 가능하다는 장점이 있습니다. 이는 특히 클라우드 환경에서 유용합니다.
1.1.5. 다양한 표준 라이브러리 제공
Go는 네트워크, 웹 서버, JSON 처리 등 다양한 기능들을 기본적으로 표준 라이브러리로 지원합니다.
예를 들어, 간단한 웹 서버를 구현한다고 하면, 다음 코드와 같이 별도의 프레임워크 없이도 간단히 구성할 수 있습니다.
package main
import (
"fmt"
"net/http"
)
func helloHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "안녕하세요, Go 서버입니다.")
}
func main() {
http.HandleFunc("/", helloHandler)
http.ListenAndServe(":8081", nil)
}

1.2. Go 언어의 단점
1.2.1. 제네릭(generic) 지원이 늦음
Go는 오랫동안 제네릭(generic
)을 지원하지 않았습니다. 이로인해 다양한 타입을 처리할 때 반복적인 코드가 늘어날 수 밖에 없었습니다. 최근 1.18 버전
부터 제네릭이 도입되었지만, 여전히 사용법이 제한적인 단점이 있습니다.
// Go 1.18 이상에서의 제네릭 사용 예시
package main
import "fmt"
func printItems[T any](items []T) {
for _, item := range items {
fmt.Println(item)
}
}
func main() {
names := []string{"아이유", "지드래곤", "뷔"}
printItems(names)
numbers := []int{1, 2, 3}
printItems(numbers)
}

과거에는 이와 같은 제네릭 사용이 불가능했기 때문에 interface로 처리하거나 별도 타입별 함수가 필요했다.
1.2.2. 번거로운 에러 처리 방식
Go는 예외 처리(exception
)를 지원하지 않습니다. 함수에서 에러를 직접 반환하고 이를 체크하는 방식을 사용합니다. 이는 코드가 장황해져 복잡해지고 가독성이 떨어질 수 있다는 단점이 있습니다.
package main
import (
"errors"
"fmt"
)
func divide(numerator, denominator int) (int, error) {
if denominator == 0 {
return 0, errors.New("0으로 나눌 수 없습니다")
}
return numerator / denominator, nil
}
func main() {
result, err := divide(10, 0)
if err != nil {
fmt.Println("에러 발생:", err)
return
}
fmt.Println("결과:", result)
}

에러를 매번 체크하고 처리해야 하므로 코드 중복이 많아질 수 있습니다.
1.2.3. 제한적인 객체 지향
Go는 클래스와 상속이 없어서 복잡하지 않고 간단할 수 있으나, 객체지향 설계에 익숙한 개발자에게는 다소 불편하게 느껴질 수 있다.
1.2.4. GUI 프로그래밍에 적합하지 않음
Go는 서버 개발이나 시스템 프로그래밍에 특화되어 있으며, 데스크탑 GUI 애플리케이션 개발에는 적합하지 않습니다. 대부분 Go의 GUI 프레임워크는 타 언어에 비해 성숙도가 낮습니다.
2. MacOSX에서 설치 방법
MacOSX에서 Go를 사용하기 위해 homebrew를 사용하여 설치하면 편리합니다. 아래 명령어를 사용하여 Go를 설치합니다.
brew install go
설치 이후 go version 명령어를 사용하여 제대로 설치가 되었는지 확인합니다.
go version
아래와 같이 버전 정보가 콘솔에 나타나면 정상적으로 설치된 것입니다.
go version go1.24.2 darwin/arm64