Alert

이 글은 Claude Code의 도움을 λ°›μ•„ μž‘μ„±λ˜μ—ˆμŠ΅λ‹ˆλ‹€

TL;DR

  • GoλŠ” λ³€μˆ˜ μ„ μ–Έ μ‹œ μžλ™μœΌλ‘œ zero valueλ₯Ό ν• λ‹Ήν•˜λ©°, Python의 Noneκ³ΌλŠ” λ‹€λ₯Έ κ°œλ…
  • μ•”μ‹œμ  νƒ€μž… λ³€ν™˜μ΄ μ—†μ–΄ float64(x) 같은 λͺ…μ‹œμ  λ³€ν™˜ ν•„μˆ˜
  • varλŠ” zero value μ΄ˆκΈ°ν™”λ‚˜ νƒ€μž… λͺ…μ‹œκ°€ ν•„μš”ν•  λ•Œ, :=λŠ” λ‚˜λ¨Έμ§€ μƒν™©μ—μ„œ μ‚¬μš©
  • μ„ μ–Έ ν›„ μ‚¬μš©ν•˜μ§€ μ•Šμ€ λ³€μˆ˜λŠ” 컴파일 μ—λŸ¬ λ°œμƒ
  • 넀이밍은 camelCase 기반이며 첫 κΈ€μž λŒ€μ†Œλ¬Έμžλ‘œ 곡개 λ²”μœ„ κ²°μ •

1. Zero Value - Python의 Noneκ³Ό λ‹€λ₯Έ κ°œλ…

Goμ—μ„œ λ³€μˆ˜λ₯Ό μ„ μ–Έλ§Œ ν•˜λ©΄ μžλ™μœΌλ‘œ zero valueκ°€ ν• λ‹Ήλœλ‹€. νƒ€μž…λ³„ 기본값은 λ‹€μŒκ³Ό κ°™λ‹€.

νƒ€μž…Zero Value
int0
float640.0
string"" (빈 λ¬Έμžμ—΄)
boolfalse
pointernil

Python은 λ³€μˆ˜λ₯Ό μ΄ˆκΈ°ν™”ν•˜μ§€ μ•Šκ³  μ‚¬μš©ν•˜λ©΄ NameErrorκ°€ λ°œμƒν•œλ‹€. GoλŠ” μ„ μ–Έλ§Œ 해도 항상 기본값이 μžˆλ‹€.

# Python - μ΄ˆκΈ°ν™” 없이 μ‚¬μš©ν•˜λ©΄ μ—λŸ¬
print(x)  # NameError: name 'x' is not defined
// Go - μ„ μ–Έλ§Œ 해도 zero valueκ°€ 할당됨
var x int
fmt.Println(x) // 0
 
var s string
fmt.Println(s) // "" (빈 λ¬Έμžμ—΄)
 
var b bool
fmt.Println(b) // false

Zero Value의 μž₯점

  • nil μ²΄ν¬λ‚˜ μ΄ˆκΈ°ν™” μ—¬λΆ€λ₯Ό λ³„λ„λ‘œ 확인할 ν•„μš”κ°€ 쀄어든닀
  • ꡬ쑰체(struct)의 λͺ¨λ“  ν•„λ“œλ„ zero value둜 μ΄ˆκΈ°ν™”λ˜λ―€λ‘œ μƒμ„±μž 없이도 μ•ˆμ „ν•˜κ²Œ μ‚¬μš© κ°€λŠ₯

2. κΈ°λ³Έ νƒ€μž… - μ •μˆ˜, λΆ€λ™μ†Œμˆ˜μ , λ¬Έμžμ—΄, λΆˆλ¦¬μ–Έ

μ •μˆ˜

GoλŠ” μ •μˆ˜ 크기λ₯Ό λͺ…μ‹œν•  수 μžˆλ‹€.

var a int     // ν”Œλž«νΌμ— 따라 32 λ˜λŠ” 64λΉ„νŠΈ
var b int8    // -128 ~ 127
var c int64   // -9223372036854775808 ~ 9223372036854775807
var d uint    // λΆ€ν˜Έ μ—†λŠ” μ •μˆ˜
var e uint8   // 0 ~ 255

μ‹€λ¬΄μ—μ„œλŠ” λŒ€λΆ€λΆ„ intλ₯Ό μ‚¬μš©ν•œλ‹€. νŠΉλ³„ν•œ 이유(λ©”λͺ¨λ¦¬ μ΅œμ ν™”, λ°”μ΄λ„ˆλ¦¬ ν”„λ‘œν† μ½œ λ“±)κ°€ μ—†μœΌλ©΄ 크기λ₯Ό λͺ…μ‹œν•  ν•„μš” μ—†λ‹€.

Python은 μ •μˆ˜ 크기에 μ œν•œμ΄ μ—†λ‹€. 10 ** 1000도 κ·Έλƒ₯ λœλ‹€. Goμ—μ„œ 같은 κ±Έ ν•˜λ €λ©΄ math/big νŒ¨ν‚€μ§€κ°€ ν•„μš”ν•˜λ‹€.

# Python - μ •μˆ˜ 크기 μ œν•œ μ—†μŒ
x = 10 ** 1000  # 잘 λ™μž‘ν•¨
// Go - μ˜€λ²„ν”Œλ‘œμš° λ°œμƒ
var x int64 = 9223372036854775807
x = x + 1  // μ˜€λ²„ν”Œλ‘œμš°: -9223372036854775808

λΆ€λ™μ†Œμˆ˜μ 

var f1 float32 = 3.14
var f2 float64 = 3.14  // κΈ°λ³Έκ°’, λŒ€λΆ€λΆ„ 이걸 μ‚¬μš©

λ¬Έμžμ—΄

Go의 λ¬Έμžμ—΄μ€ Pythonκ³Ό λ§ˆμ°¬κ°€μ§€λ‘œ immutable이닀. ν°λ”°μ˜΄ν‘œμ™€ λ°±ν‹± 두 κ°€μ§€ λ°©μ‹μœΌλ‘œ μž‘μ„±ν•œλ‹€.

s1 := "hello\nworld"   // ν°λ”°μ˜΄ν‘œ: μ΄μŠ€μΌ€μ΄ν”„ μ‹œν€€μŠ€ 처리
s2 := `hello\nworld`   // λ°±ν‹±(raw string): μ΄μŠ€μΌ€μ΄ν”„ λ¬΄μ‹œ, μ€„λ°”κΏˆ κ·ΈλŒ€λ‘œ 포함

μ˜ˆμ‹œμ— λ‚˜μ˜€λŠ” :=

μ—¬κΈ°μ„œ :=κ°€ 처음 λ‚˜μ™”λ‹€. λ³€μˆ˜λ₯Ό μ„ μ–Έν•˜λ©΄μ„œ 값을 ν•œ λ²ˆμ— ν• λ‹Ήν•˜λŠ” 짧은 μ„ μ–Έ λ¬Έλ²•μœΌλ‘œ, s1 := "hello"λŠ” var s1 = "hello"와 κ°™λ‹€. μ•žμœΌλ‘œ μ˜ˆμ‹œμ— 자주 λ“±μž₯ν•˜λŠ”λ°, varμ™€μ˜ 차이와 선택 기쀀은 4λ²ˆμ—μ„œ λ”°λ‘œ μ •λ¦¬ν•œλ‹€.

Python의 r"..." raw stringκ³Ό Go의 백틱이 λΉ„μŠ·ν•œ 역할이닀.

λΆˆλ¦¬μ–Έ

GoλŠ” λ‹€λ₯Έ νƒ€μž…μ„ bool둜 μžλ™ λ³€ν™˜ν•˜μ§€ μ•ŠλŠ”λ‹€. Pythonμ—μ„œ ν”νžˆ μ“°λŠ” truthy/falsy νŒ¨ν„΄μ΄ Goμ—μ„œλŠ” ν†΅ν•˜μ§€ μ•ŠλŠ”λ‹€.

# Python - truthy/falsy μžλ™ λ³€ν™˜
x = 0
if not x:       # λ™μž‘ν•¨
    print("zero")
 
items = []
if not items:   # λ™μž‘ν•¨
    print("empty")
// Go - λͺ…μ‹œμ  비ꡐ ν•„μˆ˜
x := 0
if x == 0 {     // if x {} λŠ” 컴파일 μ—λŸ¬
    fmt.Println("zero")
}
 
items := []int{}
if len(items) == 0 {  // if items {} λŠ” 컴파일 μ—λŸ¬
    fmt.Println("empty")
}

byte와 rune β€” 특수 μš©λ„μ˜ μ •μˆ˜ 별칭

Goμ—λŠ” μ •μˆ˜ νƒ€μž… 쀑 이름을 λ”°λ‘œ λΆ™μ—¬λ‘” 별칭이 두 κ°€μ§€ μžˆλ‹€.

  • byte = uint8의 별칭. 0~255 μ‚¬μ΄μ˜ 8λΉ„νŠΈ μ •μˆ˜ ν•˜λ‚˜λ₯Ό λ‚˜νƒ€λ‚Έλ‹€.
  • rune = int32의 별칭. μœ λ‹ˆμ½”λ“œ 문자(μ½”λ“œν¬μΈνŠΈ) ν•˜λ‚˜λ₯Ό λ‚˜νƒ€λ‚Έλ‹€.

λ‘˜ λ‹€ λ‚΄λΆ€μ μœΌλ‘œλŠ” κ·Έλƒ₯ μ •μˆ˜μ§€λ§Œ, uint8/int32 λŒ€μ‹  byte/rune을 μ“°λ©΄ β€œμ΄ 값이 μ–΄λ–€ μš©λ„μΈμ§€β€ μ½”λ“œμ—μ„œ λ°”λ‘œ λ“œλŸ¬λ‚œλ‹€.

byte β€” λ°”μ΄λ„ˆλ¦¬ 데이터λ₯Ό λ‹€λ£° λ•Œ

파일 읽기, λ„€νŠΈμ›Œν¬ 톡신, λ¬Έμžμ—΄ λ³€ν™˜ λ“± I/O κ΄€λ ¨ ν•¨μˆ˜λ“€μ€ λŒ€λΆ€λΆ„ []byte(λ°”μ΄νŠΈ 슬라이슀)λ₯Ό λ°˜ν™˜ν•œλ‹€.

// 파일 읽기 β€” κ²°κ³Όκ°€ []byte
data, err := os.ReadFile("config.json")
 
// λ¬Έμžμ—΄ ↔ λ°”μ΄νŠΈ λ³€ν™˜
b := []byte("hello")
fmt.Println(b)         // [104 101 108 108 111]
fmt.Println(string(b)) // "hello"

rune β€” 문자λ₯Ό λ‹€λ£° λ•Œ

UTF-8μ—μ„œ 문자 ν•˜λ‚˜κ°€ μ°¨μ§€ν•˜λŠ” λ°”μ΄νŠΈ μˆ˜λŠ” λ¬Έμžλ§ˆλ‹€ λ‹€λ₯΄λ‹€.

문자 μ’…λ₯˜λ°”μ΄νŠΈ μˆ˜μ˜ˆμ‹œ
ASCII (영문, 숫자, 기호)1λ°”μ΄νŠΈA, 1, !
유럽 문자 (μ•…μ„ΌνŠΈ λ“±)2λ°”μ΄νŠΈΓ±, ΓΌ
ν•œκΈ€, ν•œμž, 일본어3λ°”μ΄νŠΈκ°€, あ
이λͺ¨μ§€4λ°”μ΄νŠΈπŸ˜€

rune이 int32(4λ°”μ΄νŠΈ)인 μ΄μœ κ°€ 여기에 μžˆλ‹€. μ–΄λ–€ λ¬Έμžλ“  μ΅œλŒ€ 4λ°”μ΄νŠΈμ΄λ―€λ‘œ, rune ν•˜λ‚˜λ©΄ μ–΄λ–€ μœ λ‹ˆμ½”λ“œ λ¬Έμžλ“  담을 수 μžˆλ‹€. 반면 byteλŠ” 1λ°”μ΄νŠΈλΌμ„œ ASCII만 1:1 λŒ€μ‘λ˜κ³ , ν•œκΈ€ 'κ°€'λŠ” byte 3κ°œκ°€ ν•„μš”ν•˜λ‹€.

s := "κ°€"
fmt.Println(len(s))          // 3 β€” λ°”μ΄νŠΈ 수
fmt.Println([]byte(s))       // [234 176 128] β€” byte 3개
fmt.Println([]rune(s))       // [44032] β€” rune 1개

Python과의 차이

Pythonμ—μ„œλŠ” bytes와 str이 μ™„μ „νžˆ λ‹€λ₯Έ νƒ€μž…μ΄λ‹€. Goμ—μ„œ byte와 rune은 μ •μˆ˜μ˜ 별칭일 뿐이라 νƒ€μž… μ‹œμŠ€ν…œμ΄ ꡬ뢄해주지 μ•ŠλŠ”λ‹€. λŒ€μ‹  κ°œλ°œμžκ°€ μ΄λ¦„μœΌλ‘œ μ˜λ„λ₯Ό λ“œλŸ¬λ‚Έλ‹€.

var b byte = 72        // "λ°”μ΄λ„ˆλ¦¬ 데이터"λΌλŠ” μ˜λ„
var r rune = 'κ°€'       // "문자 처리"λΌλŠ” μ˜λ„
var b2 uint8 = 72      // 숫자 μ—°μ‚°? λ°”μ΄νŠΈ? λͺ¨ν˜Έν•¨
var r2 int32 = 'κ°€'     // 숫자 μ—°μ‚°? 문자? λͺ¨ν˜Έν•¨

λ¬Έμžμ—΄μ„ range둜 μˆœνšŒν•  λ•Œ byte와 rune의 차이가 μ‹€μ œλ‘œ λ“œλŸ¬λ‚˜λŠ”λ°, 이 뢀뢄은 μ œμ–΄ ꡬ쑰 νŽΈμ—μ„œ 더 μžμ„Ένžˆ 닀룬닀.


3. λͺ…μ‹œμ  νƒ€μž… λ³€ν™˜

GoλŠ” μ•”μ‹œμ  νƒ€μž… λ³€ν™˜μ΄ μ—†λ‹€. μ„œλ‘œ λ‹€λ₯Έ νƒ€μž…μ„ μ—°μ‚°ν•˜λ©΄ 컴파일 μ—λŸ¬κ°€ λ°œμƒν•œλ‹€.

# Python - μ•”μ‹œμ  λ³€ν™˜
result = 10 + 3.14  # intκ°€ μžλ™μœΌλ‘œ float둜 λ³€ν™˜
print(result)       # 13.14
// Go - μ•”μ‹œμ  λ³€ν™˜ μ—†μŒ
var x int = 10
var y float64 = 30.2
 
// z := x + y  // 컴파일 μ—λŸ¬: mismatched types int and float64
 
var z float64 = float64(x) + y  // λͺ…μ‹œμ  λ³€ν™˜ ν•„μˆ˜
fmt.Println(z) // 40.2

μ •μˆ˜ νƒ€μž…λΌλ¦¬λ„ 크기가 λ‹€λ₯΄λ©΄ λ³€ν™˜μ΄ ν•„μš”ν•˜λ‹€.

var a int32 = 10
var b int64 = 20
 
// c := a + b  // 컴파일 μ—λŸ¬
c := int64(a) + b  // OK

μ™œ μ΄λ ‡κ²Œ μ—„κ²©ν• κΉŒ

  • μ•”μ‹œμ  λ³€ν™˜μ€ μ˜ˆμƒμΉ˜ λͺ»ν•œ 데이터 손싀을 μΌμœΌν‚¬ 수 μžˆλ‹€ (예: float64 -> int λ³€ν™˜ μ‹œ μ†Œμˆ˜μ  버림)
  • GoλŠ” λͺ…μ‹œμ μœΌλ‘œ β€œλ‚˜λŠ” 이 λ³€ν™˜μ„ μ˜λ„ν–ˆλ‹€β€κ³  ν‘œν˜„ν•˜λ„λ‘ κ°•μ œν•œλ‹€

4. var vs := - μ–Έμ œ 뭘 μ“°λŠ”κ°€

Goμ—μ„œ λ³€μˆ˜λ₯Ό μ„ μ–Έν•˜λŠ” 방법은 크게 두 κ°€μ§€λ‹€.

var ν‚€μ›Œλ“œ

var x int = 10    // νƒ€μž…κ³Ό 값을 λͺ¨λ‘ μ§€μ •
var x = 10        // νƒ€μž… μΆ”λ‘  (int둜 좔둠됨)
var x int         // zero value둜 μ΄ˆκΈ°ν™” (x = 0)

μ—¬λŸ¬ λ³€μˆ˜λ₯Ό ν•œλ²ˆμ— μ„ μ–Έν•  μˆ˜λ„ μžˆλ‹€.

var (
    name   string
    age    int
    active bool
)

:= (짧은 μ„ μ–Έ)

x := 10           // var x = 10 κ³Ό 동일
name := "gopher"  // var name = "gopher" κ³Ό 동일

:=의 νƒ€μž… 좔둠은 컴파일 νƒ€μž„μ— μΌμ–΄λ‚œλ‹€

:=λŠ” 였λ₯Έμͺ½ κ°’μ˜ νƒ€μž…μ„ 보고 λ³€μˆ˜ νƒ€μž…μ„ μžλ™μœΌλ‘œ μ •ν•œλ‹€(10 β†’ int, "gopher" β†’ string). 단 이 좔둠은 컴파일 μ‹œμ μ— 였λ₯Έμͺ½ ν‘œν˜„μ‹μ˜ νƒ€μž…μ„ 보고 λͺ» λ°•λŠ” 것이지, μ‹€ν–‰ 쀑에 값에 따라 νƒ€μž…μ΄ λ°”λ€ŒλŠ” 게 μ•„λ‹ˆλ‹€. GoλŠ” 정적 νƒ€μž… 언어이고, :=λŠ” νƒ€μž…μ„ 두 번 μ“°μ§€ μ•Šκ²Œ ν•΄μ£ΌλŠ” 단좕 문법일 뿐이닀.

x := 10
x = "hello"   // 컴파일 μ—λŸ¬ β€” xλŠ” μ˜μ›νžˆ int

Python의 x = 10은 λ‚˜μ€‘μ— x = "hello"둜 바꿔도 λ˜μ§€λ§Œ(동적 νƒ€μž…), Go의 :=λŠ” λ³€μˆ˜μ— 정적 νƒ€μž…μ„ κ³ μ •ν•œλ‹€. κ·Έλž˜μ„œ μ»΄νŒŒμΌλŸ¬κ°€ 컴파일 μ‹œμ μ— νƒ€μž…μ„ μ•Œ 수 μ—†λŠ” κ°’(예: λͺ¨μ–‘을 λͺ¨λ₯΄λŠ” μ™ΈλΆ€ JSON)μ—λŠ” :=λ₯Ό μ“Έ 수 μ—†κ³ , 그런 κ²½μš°λŠ” 07편의 any둜 닀룬닀.

:=λŠ” ν•¨μˆ˜ μ•ˆμ—μ„œλ§Œ μ‚¬μš© κ°€λŠ₯ν•˜λ‹€. νŒ¨ν‚€μ§€ 레벨(ν•¨μˆ˜ λ°”κΉ₯)μ—μ„œλŠ” λ°˜λ“œμ‹œ varλ₯Ό 써야 ν•œλ‹€.

package main
 
var packageLevel = "OK"     // var만 κ°€λŠ₯
// badVar := "μ—λŸ¬"          // 컴파일 μ—λŸ¬: νŒ¨ν‚€μ§€ λ ˆλ²¨μ—μ„œ := μ‚¬μš© λΆˆκ°€
 
func main() {
    localVar := "OK"        // ν•¨μˆ˜ μ•ˆμ—μ„œλŠ” := μ‚¬μš© κ°€λŠ₯
    fmt.Println(localVar)
}

선택 κΈ°μ€€

상황선택
zero value둜 μ΄ˆκΈ°ν™”ν•˜κ³  싢을 λ•Œvar x int
νƒ€μž…μ„ λͺ…μ‹œμ μœΌλ‘œ μ§€μ •ν•΄μ•Ό ν•  λ•Œvar x float64 = 10
νŒ¨ν‚€μ§€ 레벨 λ³€μˆ˜var
κ·Έ μ™Έ ν•¨μˆ˜ λ‚΄λΆ€:=

:= μ‚¬μš©μ„ ν”Όν•΄μ•Ό ν•˜λŠ” 상황

:=λŠ” νŽΈλ¦¬ν•˜μ§€λ§Œ, λ‹€μŒ κ²½μš°μ—λŠ” varκ°€ 더 λ‚«λ‹€.

1. zero value둜 μ΄ˆκΈ°ν™”ν•  λ•Œ :=λ₯Ό μ“°λ©΄ λ°˜λ“œμ‹œ 였λ₯Έμͺ½μ— 값이 μžˆμ–΄μ•Ό ν•œλ‹€. zero valueκ°€ λͺ©μ μ΄λ©΄ varκ°€ μ˜λ„λ₯Ό λͺ…ν™•ν•˜κ²Œ λ“œλŸ¬λ‚Έλ‹€.

var count int          // "zero value둜 μ‹œμž‘ν•œλ‹€"λŠ” μ˜λ„κ°€ λͺ…ν™•
count := 0             // λ™μž‘μ€ κ°™μ§€λ§Œ 0이 의미 μžˆλŠ” 값인지 zero value인지 λͺ¨ν˜Έ

2. νƒ€μž…μ„ λͺ…μ‹œν•΄μ•Ό ν•  λ•Œ λ¦¬ν„°λŸ΄1μ΄λ‚˜ νƒ€μž… λ―Έμ§€μ • μƒμˆ˜λ₯Ό ν• λ‹Ήν•  λ•Œ, κΈ°λ³Έ μΆ”λ‘  νƒ€μž…μ΄ μ›ν•˜λŠ” νƒ€μž…κ³Ό λ‹€λ₯Ό 수 μžˆλ‹€.

var ratio float64 = 10   // 10μ΄μ§€λ§Œ float64둜 μ‚¬μš©ν•  κ²ƒμž„μ„ λͺ…μ‹œ
ratio := 10              // int둜 좔둠됨 β€” μ˜λ„μ™€ λ‹€λ₯Ό 수 있음

3. μ„€λ„μž‰ μ‹€μˆ˜λ₯Ό λ°©μ§€ν•  λ•Œ :=λŠ” 항상 μƒˆ λ³€μˆ˜λ₯Ό λ§Œλ“€ 수 μžˆμ–΄μ„œ, λ°”κΉ₯ λ³€μˆ˜λ₯Ό μˆ˜μ •ν•˜λ €λ‹€ μ‹€μˆ˜λ‘œ μƒˆ λ³€μˆ˜λ₯Ό λ§Œλ“€κ²Œ λœλ‹€. var둜 μ„ μ–Έν•˜λ©΄ μ΄ν›„μ—λŠ” =만 μ“°κ²Œ λ˜λ―€λ‘œ 이런 μ‹€μˆ˜λ₯Ό 쀄일 수 μžˆλ‹€.

x := 10
if true {
    x := 20           // μƒˆλ‘œμš΄ xκ°€ 생김 (λ°”κΉ₯ x와 λ‹€λ₯Έ λ³€μˆ˜!)
    fmt.Println(x)    // 20
}
fmt.Println(x)        // 10 β€” λ°”κΉ₯ xλŠ” κ·ΈλŒ€λ‘œ
 
// μ˜λ„μ μœΌλ‘œ λ°”κΉ₯ λ³€μˆ˜λ₯Ό μˆ˜μ •ν•˜λ €λ©΄ = μ‚¬μš©
x = 20

정리

  • :=λŠ” β€œμƒˆ λ³€μˆ˜ λ§Œλ“€κΈ° + κ°’ 할당”을 λ™μ‹œμ— ν•œλ‹€
  • var둜 λ¨Όμ € μ„ μ–Έν•˜λ©΄ 이후 =둜만 값을 λ°”κΎΈλ―€λ‘œ, μƒˆ λ³€μˆ˜κ°€ μƒκΈ°λŠ” μ‹€μˆ˜λ₯Ό λ°©μ§€ν•  수 μžˆλ‹€
  • 같은 μŠ€μ½”ν”„μ—μ„œ :=λ₯Ό μ“°λ©΄ κΈ°μ‘΄ λ³€μˆ˜λ₯Ό μž¬μ‚¬μš©ν•˜μ§€λ§Œ, μ•ˆμͺ½ 블둝(if, for λ“±)μ—μ„œ μ“°λ©΄ μƒˆ λ³€μˆ˜κ°€ λ§Œλ“€μ–΄μ§„λ‹€

5. μƒμˆ˜ (const)

Goμ—μ„œ μƒμˆ˜λŠ” μ‰½κ²Œ 말해 λ¦¬ν„°λŸ΄μ— 이름을 λΆ™μ΄λŠ” 방법이닀. 3.14159λΌλŠ” 숫자λ₯Ό μ½”λ“œ 곳곳에 μ“°λŠ” λŒ€μ‹  piλΌλŠ” 이름을 λΆ™μ—¬μ„œ μ“°λŠ” 것이닀.

const pi = 3.14159
const greeting = "hello"
const isDebug = false

단, Go의 constλŠ” 컴파일 νƒ€μž„μ— 값을 ν™•μ •ν•  수 μžˆλŠ” κ²ƒλ§Œ κ°€λŠ₯ν•˜λ‹€. κ·Έλž˜μ„œ μƒμˆ˜λ‘œ μ“Έ 수 μžˆλŠ” νƒ€μž…μ΄ μ œν•œμ μ΄λ‹€.

// κ°€λŠ₯: 숫자, λ¬Έμžμ—΄, bool, rune
const maxRetry = 3
const name = "gopher"
 
// λΆˆκ°€λŠ₯: λŸ°νƒ€μž„μ— λ§Œλ“€μ–΄μ§€λŠ” κ°’
// const items = []int{1, 2, 3}   // 컴파일 μ—λŸ¬: slice
// const now = time.Now()         // 컴파일 μ—λŸ¬: ν•¨μˆ˜ 호좜 κ²°κ³Ό

JavaScript의 constλŠ” β€œμž¬ν• λ‹Ή κΈˆμ§€β€μ΄κ³ , Pythonμ—λŠ” μ•„μ˜ˆ const ν‚€μ›Œλ“œκ°€ μ—†λ‹€(λŒ€λ¬Έμž λ³€μˆ˜λͺ… MAX_SIZE = 100은 관둀일 뿐 μž¬ν• λ‹Ήμ΄ κ°€λŠ₯ν•˜λ‹€). Go의 constλŠ” λ‘˜ 닀와 λ‹€λ₯΄κ²Œ β€œμ»΄νŒŒμΌ νƒ€μž„μ— 값이 κ²°μ •λ˜λŠ” κ²ƒλ§Œ ν—ˆμš©β€ν•˜λŠ” μ§„μ§œ μƒμˆ˜λ‹€.

νƒ€μž… λ―Έμ§€μ • μƒμˆ˜μ˜ μœ μ—°ν•¨

νƒ€μž…μ„ μ§€μ •ν•˜μ§€ μ•Šμ€ μƒμˆ˜λŠ” λ¦¬ν„°λŸ΄μ²˜λŸΌ μœ μ—°ν•˜κ²Œ λ™μž‘ν•œλ‹€. const x = 10μ—μ„œ 10이 λ¦¬ν„°λŸ΄μ΄λ“―, x도 아직 νƒ€μž…μ΄ μ •ν•΄μ§€μ§€ μ•Šμ€ μƒνƒœλ‹€. κ·Έλž˜μ„œ μ—¬λŸ¬ νƒ€μž…μ˜ λ³€μˆ˜μ— ν• λ‹Ήν•  수 μžˆλ‹€.

const x = 10  // νƒ€μž… λ―Έμ§€μ • μƒμˆ˜ β€” λ¦¬ν„°λŸ΄ 10에 μ΄λ¦„λ§Œ 뢙인 것
 
var a int = x       // OK
var b float64 = x   // OK
var c int64 = x     // OK

νƒ€μž…μ„ μ§€μ •ν•˜λ©΄ ν•΄λ‹Ή νƒ€μž…μœΌλ‘œ κ³ μ •λœλ‹€.

const x int = 10
 
var a int = x       // OK
// var b float64 = x   // 컴파일 μ—λŸ¬: intλ₯Ό float64에 ν• λ‹Ή λΆˆκ°€

6. μ‚¬μš© μ•ˆ ν•˜λ©΄ 컴파일 μ—λŸ¬

GoλŠ” μ„ μ–Έν•œ λ³€μˆ˜λ₯Ό μ‚¬μš©ν•˜μ§€ μ•ŠμœΌλ©΄ 컴파일 μžμ²΄κ°€ μ•ˆ λœλ‹€. import도 λ§ˆμ°¬κ°€μ§€λ‹€.

func main() {
    x := 10   // 컴파일 μ—λŸ¬: x declared and not used
}
import "fmt"  // 컴파일 μ—λŸ¬: "fmt" imported and not used
 
func main() {}

Python은 λ―Έμ‚¬μš© λ³€μˆ˜λ‚˜ importκ°€ μžˆμ–΄λ„ κ²½κ³ μ‘°μ°¨ λœ¨μ§€ μ•ŠλŠ”λ‹€(λ¦°ν„°λ₯Ό λ”°λ‘œ μ„€μ •ν•˜μ§€ μ•ŠλŠ” ν•œ). GoλŠ” μ–Έμ–΄ μ°¨μ›μ—μ„œ κ°•μ œν•œλ‹€.

νŒ¨ν‚€μ§€ 레벨 λ³€μˆ˜λŠ” μ˜ˆμ™Έ β€” κ·Έλž˜μ„œ 더 μ£Όμ˜ν•΄μ•Ό ν•œλ‹€

μ—¬κΈ°μ„œ β€œνŒ¨ν‚€μ§€ λ ˆλ²¨β€μ΄λž€ ν•¨μˆ˜ λ°”κΉ₯, 파일 μ΅œμƒμœ„μ— μ„ μ–Έν•˜λŠ” λ³€μˆ˜λ₯Ό λ§ν•œλ‹€.

package main
 
var globalCount int  // νŒ¨ν‚€μ§€ 레벨 λ³€μˆ˜ β€” ν•¨μˆ˜ λ°”κΉ₯에 μ„ μ–Έ
 
func main() {
    localVar := 10   // μ§€μ—­ λ³€μˆ˜ β€” ν•¨μˆ˜ μ•ˆμ— μ„ μ–Έ
}

λ¬Έμ œλŠ” Go μ»΄νŒŒμΌλŸ¬κ°€ νŒ¨ν‚€μ§€ 레벨 λ³€μˆ˜λŠ” λ―Έμ‚¬μš© 검사λ₯Ό ν•˜μ§€ μ•ŠλŠ”λ‹€λŠ” 것이닀. μ„ μ–Έλ§Œ 해놓고 아무 λ°μ„œλ„ μ•ˆ 써도 컴파일이 잘 λœλ‹€. μ»΄νŒŒμΌλŸ¬κ°€ μž‘μ•„μ£Όμ§€ μ•ŠμœΌλ‹ˆ 죽은 μ½”λ“œκ°€ μŒ“μ΄κΈ° 쉽닀.

κ·Έλž˜μ„œ νŒ¨ν‚€μ§€ λ ˆλ²¨μ—μ„œλŠ” λ³€μˆ˜ 선언을 μ΅œμ†Œν™”ν•˜κ³ , κΌ­ ν•„μš”ν•˜λ‹€λ©΄ 사싀상 λ³€κ²½ν•˜μ§€ μ•Šμ„ κ°’(μƒμˆ˜μ— κ°€κΉŒμš΄ 것)만 λ‘λŠ” 것이 μ’‹λ‹€.

_ 둜 λͺ…μ‹œμ  λ¬΄μ‹œ

값을 λ°›μ•„μ•Ό ν•˜μ§€λ§Œ μ‚¬μš©ν•˜μ§€ μ•Šμ„ λ•ŒλŠ” _(blank identifier)λ₯Ό μ‚¬μš©ν•œλ‹€.

// ν•¨μˆ˜κ°€ 두 값을 λ°˜ν™˜ν•˜λŠ”λ° ν•˜λ‚˜λ§Œ ν•„μš”ν•  λ•Œ
value, _ := someFunction()
 
// rangeμ—μ„œ μΈλ±μŠ€κ°€ ν•„μš” 없을 λ•Œ
for _, item := range items {
    fmt.Println(item)
}

Python의 _ 관둀와 λΉ„μŠ·ν•˜μ§€λ§Œ, Goμ—μ„œλŠ” 이걸 μ•ˆ μ“°λ©΄ 컴파일 μ—λŸ¬κ°€ λ‚˜λ‹ˆ 선택이 μ•„λ‹ˆλΌ ν•„μˆ˜λ‹€.


7. 넀이밍 μ»¨λ²€μ…˜

GoλŠ” snake_caseκ°€ μ•„λ‹ˆλΌ camelCaseλ₯Ό μ‚¬μš©ν•œλ‹€.

// Go μŠ€νƒ€μΌ
userName := "gopher"
maxRetryCount := 3
isActive := true
 
// Python μŠ€νƒ€μΌ (Goμ—μ„œλŠ” λΉ„κΆŒμž₯)
// user_name := "gopher"
// max_retry_count := 3

첫 κΈ€μž λŒ€μ†Œλ¬Έμž = 곡개 λ²”μœ„

Goμ—μ„œ κ°€μž₯ λ…νŠΉν•œ 넀이밍 κ·œμΉ™μ΄λ‹€. 첫 κΈ€μžκ°€ λŒ€λ¬Έμžλ©΄ exported(λ‹€λ₯Έ νŒ¨ν‚€μ§€μ—μ„œ μ ‘κ·Ό κ°€λŠ₯), μ†Œλ¬Έμžλ©΄ unexported(νŒ¨ν‚€μ§€ λ‚΄λΆ€ μ „μš©)이닀.

package user
 
var MaxAge = 150       // exported: λ‹€λ₯Έ νŒ¨ν‚€μ§€μ—μ„œ user.MaxAge둜 μ ‘κ·Ό κ°€λŠ₯
var defaultRole = "guest"  // unexported: νŒ¨ν‚€μ§€ λ‚΄λΆ€μ—μ„œλ§Œ μ‚¬μš©
 
func GetName() string { ... }   // exported
func validate() bool { ... }    // unexported

Pythonμ—μ„œλŠ” _ μ ‘λ‘μ‚¬λ‘œ λΉ„κ³΅κ°œλ₯Ό ν‘œμ‹œν•˜λŠ” κ΄€λ‘€κ°€ μžˆμ§€λ§Œ, μ‹€μ œλ‘œ 접근을 λ§‰μ§€λŠ” μ•ŠλŠ”λ‹€.

# Python - 관둀적 λΉ„κ³΅κ°œ (μ‹€μ œλ‘œλŠ” μ ‘κ·Ό κ°€λŠ₯)
class User:
    def __init__(self):
        self._name = "private"     # 관둀적 λΉ„κ³΅κ°œ
        self.__secret = "hidden"   # name mangling (μ—¬μ „νžˆ μ ‘κ·Ό κ°€λŠ₯)
 
u = User()
print(u._name)           # μ ‘κ·Ό κ°€λŠ₯ (경고만)
print(u._User__secret)   # 이것도 μ ‘κ·Ό κ°€λŠ₯

GoλŠ” μ»΄νŒŒμΌλŸ¬κ°€ μ ‘κ·Ό μ œμ–΄λ₯Ό κ°•μ œν•œλ‹€. unexported μ‹λ³„μžλŠ” λ‹€λ₯Έ νŒ¨ν‚€μ§€μ—μ„œ μ•„μ˜ˆ μ‚¬μš©ν•  수 μ—†λ‹€.

μš”μ•½: Python vs Go 넀이밍

  • Python: snake_case, _prefix둜 λΉ„κ³΅κ°œ ν‘œμ‹œ (κ΄€λ‘€)
  • Go: camelCase, 첫 κΈ€μž λŒ€λ¬Έμž/μ†Œλ¬Έμžλ‘œ 곡개 λ²”μœ„ κ²°μ • (컴파일러 κ°•μ œ)

Footnotes

  1. λ¦¬ν„°λŸ΄(literal)은 μ½”λ“œμ— 직접 μ“΄ κ°’ κ·Έ 자체λ₯Ό λ§ν•œλ‹€. 42, "hello", 3.14 같은 것듀이 λ¦¬ν„°λŸ΄μ΄λ‹€. λ³€μˆ˜λͺ…은 값을 κ°€λ¦¬ν‚€λŠ” 이름이고, λ¦¬ν„°λŸ΄μ€ 이름 없이 μ½”λ“œμ— λ°•ν˜€ μžˆλŠ” λ‚ κ²ƒμ˜ 값이닀. ↩