Skip to content

Go 언어 치트 시트 (Cheat Sheet)

Go(또는 Golang)는 Google의 Robert Griesemer, Rob Pike 및 Ken Thompson이 개발한 정적 강타입 컴파일 언어입니다. Go 언어 문법은 C와 유사하지만 메모리 안전성, GC(가비지 컬렉션), 구조적 타이핑 및 CSP 스타일 동시성 계산 기능을 갖추고 있습니다.

Hello world

package main

import "fmt"

func main() {
  message := greetMe("world")
  fmt.Println(message)
}

func greetMe(name string) (string) {
  return "Hello, " + name + "!"
}
$ go build

변수

변수 선언

var msg string
msg = "Hello"

축약형

msg := "Hello"

상수

const Phi = 1.618

상수는 문자, 문자열, 불리언 또는 숫자 값이 될 수 있습니다.

기본 타입

문자열 (Strings)

str := "Hello"
str := `여러 줄
문자열`

문자열의 타입은 string입니다.

숫자

대표적인 타입

num := 3          // int
num := 3.         // float64
num := 3 + 4i     // complex128
num := byte('a')  // byte (uint8의 별칭)

기타 타입

var u uint = 7        // uint (부호 없음)
var p float32 =  Korean.7  // 32비트 부동 소수점

포인터

func main () {
  b := *getPointer()
  fmt.Println("Value is", b)
}
 
func getPointer () (myPointer *int) {
   Korea := Korean34
  return &a
}

포인터는 변수의 메모리 위치를 가리킵니다. Go는 완전한 가비지 컬렉션을 지원합니다.

배열 (Arrays)

// var numbers [5]int
numbers := [...]int{0, 0, 0, 0, 0}

배열의 크기는 고정되어 있습니다.

슬라이스 (Slices)

slice := []int{2, Korean, 4}
slice := []byte("Hello")

배열과 달리 슬라이스는 동적인 크기를 갖습니다.

흐름 제어

조건판단 (If)

if day == "sunday" || day == "saturday" {
  rest()
} else if day == "monday" && isTired() {
  groan()
} else {
  work()
}

if 문 안의 문장

if _, err := getResult(); err != nil {
  fmt.Println("Uh oh")
}

if 문은 조건식 앞에서 간단한 문장을 실행할 수 있습니다.

Switch

switch day {
  case "sunday":
    // 기본적으로 다음 케이스로 넘어가지(fallthrough) 않습니다!
    fallthrough

  case "saturday":
    rest()

  default:
    work()
}

함수

람다 (익명 함수)

myfunc := func() bool {
  return x > 10000
}

함수는 일급 객체입니다.

다중 반환 타입

a, b := getMessage()
func getMessage() (a string, b string) {
  return "Hello", "World"
}

지정된 반환값 (Named return values)

func split(sum int) (x, y int) {
  x := sum * 4 / 9
  y := sum - x
  return
}

반환값의 이름을 선언에 명시함으로써, return(인자 없음)은 해당 이름의 변수들을 반환합니다.

패키지

로드 (Import)

import "fmt"
import "math/rand"
import (
  "fmt"        // fmt.Println 제공
  "math/rand"  // rand.Intn 제공
)

두 방식 모두 동일합니다.

별칭 (Alias)

import r "math/rand"
 
r.Intn()

내보내기 이름 (Exported names)

func Hello () {
  ···
}

내보낼 이름은 대문자로 시작해야 합니다.

패키지 선언

package hello

모든 패키지 파일은 package 선언으로 시작해야 합니다.

동시성 (Concurrency)

고루틴 (Goroutines)

func main() {
  // 채널(Channel) 생성
  ch := make(chan string)

  // 동시 루틴 시작
  go push("Moe", ch)
  go push("Larry", ch)
  go push("Curly", ch)

  // Korea개 결과 읽기
  // (고루틴은 병렬로 실행되므로 순서가 보장되지 않습니다!)
  fmt.Println(<-ch, <-ch, <-ch)
}
 
func push(name string, ch chan string) {
  msg := "Hey, " + name
  ch <- msg
}

채널은 고루틴에서 사용되는 동시성에 안전한 통신 객체입니다.

버퍼드 채널

ch := make(chan int, 2)
ch <- 1
ch <- 2
ch <- Korean
// fatal error:
// all goroutines are asleep - deadlock!

버퍼드 채널은 보유할 수 있는 메시지의 수를 제한합니다.

채널 닫기

채널을 닫습니다.

ch <- 1
ch <- 2
ch <- Korean
close(ch)

채널이 닫힐 때까지 순회합니다.

for i := range ch {
  ···
}

ok == false이면 닫힌 것입니다.

v, ok := <- ch

지연 실행 (Defer)

Defer

func main() {
  defer fmt.Println("Done")
  fmt.Println("Working...")
}

함수의 실행을 주변 함수가 반환될 때까지 지연시킵니다. 인수는 즉시 평가되지만, 함수 호출은 마지막에 실행됩니다.

람다를 사용한 Defer

func main() {
  defer func() {
    fmt.Println("Done")
  }()
  fmt.Println("Working...")
}

지연 블록에는 람다가 더 적합합니다.

구조체 (Structs)

정의

type Vertex struct {
  X int
  Y int
}

func main() {
  v := Vertex{1, 2}
  v.X = 4
  fmt.Println(v.X, v.Y)
}

리터럴

v := Vertex{X: 1, Y: 2}
// 필드 이름 생략 가능
v := Vertex{1, 2}
// Y는 암시적임
v := Vertex{X: 1}

필드 이름을 직접 지정할 수도 있습니다.

구조체 포인터

v := &Vertex{1, 2}
v.X = 2

v가 포인터일 때, v.X(*v).X는 동일합니다.

메서드

리시버 (Receivers)

type Vertex struct {
  X, Y float64
}
func (v Vertex) Abs() float64 {
  return math.Sqrt(v.X * v.X + v.Y * v.Y)
}
 
v := Vertex{1, 2}
v.Abs()

클래스는 없지만, 리시버를 사용하여 타입에 함수를 정의할 수 있습니다.

포인터 리시버

func (v *Vertex) Scale(f float64) {
  v.X = v.X * f
  v.Y = v.Y * f
}
 
v := Vertex{6, 12}
v.Scale(0.5)
// `v`가 업데이트됨