Alert

์ด ๊ธ€์€ Claude Code์˜ ๋„์›€์„ ๋ฐ›์•„ ์ž‘์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค

TL;DR

  • Go ๋ฐฐ์—ด์€ ํฌ๊ธฐ๊ฐ€ ํƒ€์ž…์˜ ์ผ๋ถ€์ด๋ฏ€๋กœ ์‹ค๋ฌด์—์„œ๋Š” ์Šฌ๋ผ์ด์Šค๋ฅผ ์‚ฌ์šฉ
  • ์Šฌ๋ผ์ด์Šค๋Š” Python list์™€ ์œ ์‚ฌํ•˜์ง€๋งŒ append ์‹œ ๋ฐ˜๋“œ์‹œ ์žฌํ• ๋‹น ํ•„์š”
  • ๋งต์€ Python dict์™€ ๊ฑฐ์˜ ๋™์ผํ•˜๋‚˜ nil ๋งต์— ์“ฐ๊ธฐํ•˜๋ฉด panic ๋ฐœ์ƒ
  • ๊ตฌ์กฐ์ฒด๋Š” Python dataclass์™€ ๋น„์Šทํ•œ ์—ญํ• ์„ ํ•˜๋Š” Go์˜ ๋ณตํ•ฉ ํƒ€์ž…

1. ๋ฐฐ์—ด โ€” ๊ฑฐ์˜ ์•ˆ ์“ฐ์ง€๋งŒ ์•Œ์•„์•ผ ํ•˜๋Š” ์ด์œ 

Go์˜ ๋ฐฐ์—ด์€ C/C++์ฒ˜๋Ÿผ ๊ณ ์ • ํฌ๊ธฐ๋ฅผ ๊ฐ€์ง„๋‹ค. ์ค‘์š”ํ•œ ์ ์€ ํฌ๊ธฐ ์ž์ฒด๊ฐ€ ํƒ€์ž…์˜ ์ผ๋ถ€๋ผ๋Š” ๊ฒƒ์ด๋‹ค.

var a [3]int  // [3]int ํƒ€์ž…
var b [4]int  // [4]int ํƒ€์ž… โ€” a์™€ ๋‹ค๋ฅธ ํƒ€์ž…

[3]int์™€ [4]int๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ํƒ€์ž…์ด๊ธฐ ๋•Œ๋ฌธ์— ๋Œ€์ž…๋„, ๋น„๊ต๋„ ์•ˆ ๋œ๋‹ค. Python์—์„œ ๋ฆฌ์ŠคํŠธ ๊ธธ์ด๊ฐ€ ํƒ€์ž…์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๋Š” ๊ฒƒ๊ณผ ๋Œ€์กฐ์ ์ด๋‹ค.

a = b  // ์ปดํŒŒ์ผ ์—๋Ÿฌ: cannot use b (type [4]int) as type [3]int

๋ฐฐ์—ด์€ ์–ธ์ œ ์“ฐ๋Š”๊ฐ€

  • ์‹ค๋ฌด์—์„œ ๋ฐฐ์—ด์„ ์ง์ ‘ ์“ธ ์ผ์€ ๊ฑฐ์˜ ์—†๋‹ค
  • ์Šฌ๋ผ์ด์Šค์˜ ๋‚ด๋ถ€ ๊ตฌ์กฐ๋ฅผ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•œ ๋ฐฐ๊ฒฝ ์ง€์‹ ์ •๋„๋กœ ์•Œ์•„๋‘๋ฉด ๋œ๋‹ค
  • SHA-256 ํ•ด์‹œ๊ฐ’์ฒ˜๋Ÿผ ํฌ๊ธฐ๊ฐ€ ๊ณ ์ •๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃฐ ๋•Œ ๊ฐ€๋” ๋“ฑ์žฅํ•œ๋‹ค

2. ์Šฌ๋ผ์ด์Šค โ€” Python list์˜ Go ๋ฒ„์ „

์Šฌ๋ผ์ด์Šค๋Š” Go์—์„œ ๊ฐ€์žฅ ๋งŽ์ด ์“ฐ๋Š” ์ปฌ๋ ‰์…˜ ํƒ€์ž…์ด๋‹ค. Python์˜ list์™€ ์—ญํ• ์ด ๊ฐ™๋‹ค.

2.1 ์„ ์–ธ๊ณผ ์ดˆ๊ธฐํ™”

// ๋ฆฌํ„ฐ๋Ÿด๋กœ ์„ ์–ธ
var nums = []int{10, 20, 30}
 
// ์งง์€ ์„ ์–ธ
names := []string{"alice", "bob"}

Python๊ณผ ๋น„๊ตํ•˜๋ฉด ์ด๋ ‡๋‹ค.

# Python
nums = [10, 20, 30]
names = ["alice", "bob"]
// Go
nums := []int{10, 20, 30}
names := []string{"alice", "bob"}

2.2 nil ์Šฌ๋ผ์ด์Šค

์„ ์–ธ๋งŒ ํ•˜๊ณ  ์ดˆ๊ธฐํ™”ํ•˜์ง€ ์•Š์œผ๋ฉด nil ์Šฌ๋ผ์ด์Šค๊ฐ€ ๋œ๋‹ค.

var x []int
fmt.Println(x == nil)  // true
fmt.Println(len(x))    // 0

Python์˜ ๋นˆ ๋ฆฌ์ŠคํŠธ []์™€ ๋‹ค๋ฅด๋‹ค. Python์—์„œ []๋Š” ์œ ํšจํ•œ ๋นˆ ๋ฆฌ์ŠคํŠธ์ง€๋งŒ, Go์˜ nil ์Šฌ๋ผ์ด์Šค๋Š” ์•„์ง ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ํ• ๋‹น๋˜์ง€ ์•Š์€ ์ƒํƒœ๋‹ค. ๋‹ค๋งŒ len, append ๋“ฑ์€ nil ์Šฌ๋ผ์ด์Šค์—์„œ๋„ ์ •์ƒ ๋™์ž‘ํ•œ๋‹ค.

# Python
x = []       # ๋นˆ ๋ฆฌ์ŠคํŠธ, None์ด ์•„๋‹˜
x is None    # False
// Go
var x []int  // nil ์Šฌ๋ผ์ด์Šค
x == nil     // true
x = append(x, 1)  // ์ •์ƒ ๋™์ž‘

2.3 append โ€” ๋ฐ˜๋“œ์‹œ ์žฌํ• ๋‹น

append๋Š” ์›๋ณธ ์Šฌ๋ผ์ด์Šค๋ฅผ ์ˆ˜์ •ํ•˜์ง€ ์•Š๊ณ  ์ƒˆ ์Šฌ๋ผ์ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ๋ฐ˜๋“œ์‹œ ๊ฒฐ๊ณผ๋ฅผ ์žฌํ• ๋‹นํ•ด์•ผ ํ•œ๋‹ค.

x := []int{1, 2, 3}
x = append(x, 4)          // ๋ฐ˜๋“œ์‹œ x์— ๋‹ค์‹œ ๋Œ€์ž…
x = append(x, 5, 6, 7)    // ์—ฌ๋Ÿฌ ๊ฐ’ ๋™์‹œ ์ถ”๊ฐ€

Python์˜ extend์— ํ•ด๋‹นํ•˜๋Š” ํŒจํ„ด์€ ... ์—ฐ์‚ฐ์ž๋ฅผ ์“ด๋‹ค.

# Python
a = [1, 2, 3]
b = [4, 5, 6]
a.extend(b)
// Go
a := []int{1, 2, 3}
b := []int{4, 5, 6}
a = append(a, b...)  // b๋ฅผ ํ’€์–ด์„œ append

append๋ฅผ ์žฌํ• ๋‹นํ•˜์ง€ ์•Š์œผ๋ฉด?

append(x, 10)์ฒ˜๋Ÿผ ๊ฒฐ๊ณผ๋ฅผ ๋ฒ„๋ฆฌ๋ฉด ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์—๋Ÿฌ๋ฅผ ๋‚ธ๋‹ค. Python์˜ list.append()๋Š” ์›๋ณธ์„ ์ง์ ‘ ์ˆ˜์ •(in-place)ํ•˜๋ฏ€๋กœ ๋ฐ˜ํ™˜๊ฐ’์„ ์“ธ ํ•„์š”๊ฐ€ ์—†์ง€๋งŒ, Go๋Š” ๋‹ค๋ฅด๋‹ค.

2.4 ์Šฌ๋ผ์ด์‹ฑ โ€” ๋ถ€๋ถ„ ์ถ”์ถœ๊ณผ ์ €์žฅ ๊ณต๊ฐ„ ๊ณต์œ 

์Šฌ๋ผ์ด์Šค์—์„œ ์ผ๋ถ€๋ฅผ ์ž˜๋ผ๋‚ด๋Š” ๋ฌธ๋ฒ•์€ Python๊ณผ ๊ฑฐ์˜ ๊ฐ™๋‹ค.

x := []int{10, 20, 30, 40, 50}
y := x[1:3]    // [20, 30] โ€” ์ธ๋ฑ์Šค 1๋ถ€ํ„ฐ 3 ๋ฏธ๋งŒ
z := x[:2]     // [10, 20]
w := x[2:]     // [30, 40, 50]
# Python โ€” ๋™์ผํ•œ ๋ฌธ๋ฒ•
x = [10, 20, 30, 40, 50]
y = x[1:3]    # [20, 30]

ํ•˜์ง€๋งŒ ๋™์ž‘ ๋ฐฉ์‹์ด ๊ทผ๋ณธ์ ์œผ๋กœ ๋‹ค๋ฅด๋‹ค. Python์€ ์ƒˆ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋งŒ๋“ค๊ณ , Go๋Š” ์›๋ณธ ๋ฐฐ์—ด์„ ๊ณต์œ ํ•œ๋‹ค.

x := []int{10, 20, 30, 40, 50}
y := x[1:3]    // [20, 30]
y[0] = 999
 
fmt.Println(x) // [10, 999, 30, 40, 50] โ€” ์›๋ณธ๋„ ๋ฐ”๋€œ!
fmt.Println(y) // [999, 30]
# Python โ€” ์›๋ณธ์— ์˜ํ–ฅ ์—†์Œ
x = [10, 20, 30, 40, 50]
y = x[1:3]
y[0] = 999
print(x)  # [10, 20, 30, 40, 50] โ€” ์›๋ณธ ๊ทธ๋Œ€๋กœ

Go์—์„œ ์Šฌ๋ผ์ด์‹ฑ์€ ๋ณต์‚ฌ๊ฐ€ ์•„๋‹ˆ๋ผ ๊ฐ™์€ ๋‚ด๋ถ€ ๋ฐฐ์—ด์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ทฐ(view) ๋ฅผ ๋งŒ๋“ ๋‹ค. ๊ทธ๋ž˜์„œ ํ•œ์ชฝ์„ ์ˆ˜์ •ํ•˜๋ฉด ๋‹ค๋ฅธ ์ชฝ์—๋„ ์˜ํ–ฅ์ด ๊ฐ„๋‹ค.

๋” ์œ„ํ—˜ํ•œ ๊ฒฝ์šฐ๋Š” ์Šฌ๋ผ์ด์‹ฑํ•œ ๋’ค append๋ฅผ ํ•  ๋•Œ๋‹ค. ์šฉ๋Ÿ‰์ด ๋‚จ์•„์žˆ์œผ๋ฉด ์›๋ณธ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฎ์–ด์“ธ ์ˆ˜ ์žˆ๋‹ค.

x := []int{10, 20, 30, 40, 50}
y := x[:2]     // [10, 20], cap(y) = 5 โ€” ์›๋ณธ์˜ ์šฉ๋Ÿ‰์„ ๊ทธ๋Œ€๋กœ ๊ฐ€์ ธ๊ฐ
 
y = append(y, 999)
fmt.Println(x) // [10, 20, 999, 40, 50] โ€” x[2]๊ฐ€ ๋ฎ์–ด์จ์ง!
fmt.Println(y) // [10, 20, 999]

์ด ๋ฌธ์ œ๋ฅผ ๋ฐฉ์ง€ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ๋‘ ๊ฐ€์ง€ ์žˆ๋‹ค.

๋ฐฉ๋ฒ• 1: ์™„์ „ํ•œ ์Šฌ๋ผ์ด์Šค ํ‘œํ˜„์‹ (3-index slice)

์„ธ ๋ฒˆ์งธ ์ธ๋ฑ์Šค๋กœ ์šฉ๋Ÿ‰์„ ์ œํ•œํ•  ์ˆ˜ ์žˆ๋‹ค. x[start:end:cap] ํ˜•ํƒœ๋‹ค.

x := []int{10, 20, 30, 40, 50}
y := x[:2:2]   // [10, 20], cap(y) = 2 โ€” ์šฉ๋Ÿ‰์„ ๊ธธ์ด์™€ ๊ฐ™๊ฒŒ ์ œํ•œ
 
y = append(y, 999)  // ์šฉ๋Ÿ‰ ์ดˆ๊ณผ โ†’ ์ƒˆ ๋ฐฐ์—ด ํ• ๋‹น
fmt.Println(x)      // [10, 20, 30, 40, 50] โ€” ์›๋ณธ ์•ˆ์ „
fmt.Println(y)      // [10, 20, 999]

์„ธ ๋ฒˆ์งธ ๊ฐ’์ด ์šฉ๋Ÿ‰์˜ ๋ ์œ„์น˜๋ฅผ ์ง€์ •ํ•œ๋‹ค. x[:2:2]๋Š” โ€œ๊ธธ์ด 2, ์šฉ๋Ÿ‰๋„ 2โ€๊ฐ€ ๋˜์–ด append ์‹œ ๋ฐ˜๋“œ์‹œ ์ƒˆ ๋ฐฐ์—ด์ด ํ• ๋‹น๋œ๋‹ค.

๋ฐฉ๋ฒ• 2: copy ํ•จ์ˆ˜

์•„์˜ˆ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณต์‚ฌํ•ด์„œ ๋…๋ฆฝ์ ์ธ ์Šฌ๋ผ์ด์Šค๋ฅผ ๋งŒ๋“ ๋‹ค. Python์˜ ์Šฌ๋ผ์ด์‹ฑ(x[1:3])์ด ํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฒฐ๊ณผ์ ์œผ๋กœ ๊ฐ™๋‹ค.

x := []int{10, 20, 30, 40, 50}
y := make([]int, 2)   // ๊ธธ์ด 2์งœ๋ฆฌ ์Šฌ๋ผ์ด์Šค๋ฅผ ๋ฏธ๋ฆฌ ๋งŒ๋“ ๋‹ค (make๋Š” 2.6์—์„œ ์ž์„ธํžˆ)
copy(y, x[1:3])       // x[1:3]์˜ ๋‚ด์šฉ์„ y์— ๋ณต์‚ฌ
 
y[0] = 999
fmt.Println(x)     // [10, 20, 30, 40, 50] โ€” ์›๋ณธ ์•ˆ์ „
fmt.Println(y)     // [999, 30]

copy(dst, src)๋Š” ๋‘ ์Šฌ๋ผ์ด์Šค ์ค‘ ์งง์€ ์ชฝ์˜ ๊ธธ์ด๋งŒํผ๋งŒ ๋ณต์‚ฌํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ๋Œ€์ƒ(dst)์—๋Š” ๋ฏธ๋ฆฌ ๊ธธ์ด๊ฐ€ ํ™•๋ณด๋œ ์Šฌ๋ผ์ด์Šค๊ฐ€ ํ•„์š”ํ•˜๊ณ , ์—ฌ๊ธฐ์„œ make๋ฅผ ์“ด๋‹ค. ๋ฐ˜ํ™˜๊ฐ’์€ ์‹ค์ œ๋กœ ๋ณต์‚ฌ๋œ ์›์†Œ ์ˆ˜๋‹ค.

์Šฌ๋ผ์ด์‹ฑ ์‹œ ์ฃผ์˜

  • Go์˜ ์Šฌ๋ผ์ด์‹ฑ์€ ๋ณต์‚ฌ๊ฐ€ ์•„๋‹ˆ๋ผ ๋ทฐ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด๋‹ค
  • ์›๋ณธ๊ณผ ๋ถ„๋ฆฌํ•˜๊ณ  ์‹ถ์œผ๋ฉด copy๋ฅผ ์“ฐ๊ฑฐ๋‚˜, 3-index slice(x[:2:2])๋กœ ์šฉ๋Ÿ‰์„ ์ œํ•œํ•ด์•ผ ํ•œ๋‹ค
  • Python ๊ฐœ๋ฐœ์ž๋Š” ์Šฌ๋ผ์ด์‹ฑ์ด ํ•ญ์ƒ ๋ณต์‚ฌ์ธ ๊ฒƒ์— ์ต์ˆ™ํ•˜๋ฏ€๋กœ, Go์—์„œ ์ด ์ฐจ์ด๋ฅผ ๋†“์น˜๊ธฐ ์‰ฝ๋‹ค

2.5 len๊ณผ cap

์Šฌ๋ผ์ด์Šค์—๋Š” ๊ธธ์ด(length)์™€ ์šฉ๋Ÿ‰(capacity) ๋‘ ๊ฐ€์ง€ ์†์„ฑ์ด ์žˆ๋‹ค.

x := []int{1, 2, 3}
fmt.Println(len(x))  // 3 โ€” ํ˜„์žฌ ์›์†Œ ๊ฐœ์ˆ˜
fmt.Println(cap(x))  // 3 โ€” ๋‚ด๋ถ€ ๋ฐฐ์—ด์˜ ์ „์ฒด ํฌ๊ธฐ
 
x = append(x, 4)
fmt.Println(len(x))  // 4
fmt.Println(cap(x))  // 6 โ€” ์šฉ๋Ÿ‰์ด ๋ถ€์กฑํ•ด์„œ 2๋ฐฐ๋กœ ํ™•์žฅ๋จ
  • len: ํ˜„์žฌ ๋“ค์–ด์žˆ๋Š” ์›์†Œ ์ˆ˜
  • cap: ์žฌํ• ๋‹น ์—†์ด ๋‹ด์„ ์ˆ˜ ์žˆ๋Š” ์ตœ๋Œ€ ์›์†Œ ์ˆ˜

์šฉ๋Ÿ‰์ด ๋ถ€์กฑํ•˜๋ฉด Go ๋Ÿฐํƒ€์ž„์ด ๋” ํฐ ๋ฐฐ์—ด์„ ์ƒˆ๋กœ ํ• ๋‹นํ•˜๊ณ  ๊ธฐ์กด ๋ฐ์ดํ„ฐ๋ฅผ ๋ณต์‚ฌํ•œ๋‹ค. ํ™•์žฅ ๊ทœ์น™์€ ๋Œ€๋žต ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค. (Go 1.14 ๊ธฐ์ค€)

  • ํ˜„์žฌ ์šฉ๋Ÿ‰์ด 1024 ๋ฏธ๋งŒ์ด๋ฉด 2๋ฐฐ๋กœ ํ™•์žฅ
  • 1024 ์ด์ƒ์ด๋ฉด ์•ฝ 25%์”ฉ ํ™•์žฅ

Python์˜ list๋„ ๋‚ด๋ถ€์ ์œผ๋กœ ๋น„์Šทํ•œ ๋™์  ๋ฐฐ์—ด ๊ตฌ์กฐ๋ฅผ ์“ด๋‹ค. ๋‹ค๋งŒ Python์—์„œ๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ capacity๋ฅผ ์ง์ ‘ ๊ด€๋ฆฌํ•  ์ผ์ด ์—†๋‹ค.

2.6 make โ€” ์šฉ๋Ÿ‰์„ ๋ฏธ๋ฆฌ ์ง€์ •

ํฌ๊ธฐ๋ฅผ ๋ฏธ๋ฆฌ ์•Œ๊ณ  ์žˆ์œผ๋ฉด make๋กœ ์Šฌ๋ผ์ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๋ฉด ๋ถˆํ•„์š”ํ•œ ์žฌํ• ๋‹น์„ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.

// ๊ธธ์ด 5, ์šฉ๋Ÿ‰ 5 (๊ธฐ๋ณธ๊ฐ’์œผ๋กœ cap == len)
a := make([]int, 5)
// a = [0, 0, 0, 0, 0]
 
// ๊ธธ์ด 5, ์šฉ๋Ÿ‰ 10
b := make([]int, 5, 10)
// b = [0, 0, 0, 0, 0], cap(b) = 10

๊ธธ์ด 0, ์šฉ๋Ÿ‰๋งŒ ์ง€์ •ํ•˜๋Š” ํŒจํ„ด

ํฌ๊ธฐ๋ฅผ ์˜ˆ์ƒํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์ฒ˜์Œ์—๋Š” ๋น„์–ด์žˆ์–ด์•ผ ํ•  ๋•Œ ์ž์ฃผ ์“ด๋‹ค.

result := make([]int, 0, 100)
for _, v := range data {
    result = append(result, v*2)
}

2.7 ์–ธ์ œ ๋ญ˜ ์“ฐ๋Š”๊ฐ€

์ƒํ™ฉ๊ถŒ์žฅ ๋ฐฉ์‹์˜ˆ์‹œ
๋น„์–ด์žˆ์„ ์ˆ˜๋„ ์žˆ๋Š” ๊ฒฝ์šฐnil ์Šฌ๋ผ์ด์Šคvar data []int
์ดˆ๊ธฐ๊ฐ’์ด ์žˆ๋Š” ๊ฒฝ์šฐ๋ฆฌํ„ฐ๋Ÿดnums := []int{1, 2, 3}
ํฌ๊ธฐ๋ฅผ ์˜ˆ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐmakemake([]int, 0, n)
// JSON ์‘๋‹ต ๋“ฑ์—์„œ ๊ฐ’์ด ์—†์„ ์ˆ˜๋„ ์žˆ์œผ๋ฉด nil ์Šฌ๋ผ์ด์Šค
var data []int
 
// ๊ณ ์ •๋œ ์ดˆ๊ธฐ๊ฐ’์ด ์žˆ์œผ๋ฉด ๋ฆฌํ„ฐ๋Ÿด
defaults := []string{"en", "ko", "ja"}
 
// ๋ฃจํ”„ ๊ฒฐ๊ณผ๋ฅผ ๋ชจ์„ ๋•Œ ํฌ๊ธฐ๋ฅผ ๋ฏธ๋ฆฌ ์žก์œผ๋ฉด ์„ฑ๋Šฅ ์ด๋“
result := make([]int, 0, len(input))

3. ๋งต โ€” Python dict์™€ ๊ฑฐ์˜ ๊ฐ™๋‹ค

Go์˜ map์€ Python์˜ dict์™€ ๊ธฐ๋Šฅ์ด ๊ฑฐ์˜ ๋™์ผํ•˜๋‹ค. ํ‚ค-๊ฐ’ ์Œ์„ ์ €์žฅํ•˜๋Š” ํ•ด์‹œ ํ…Œ์ด๋ธ” ๊ธฐ๋ฐ˜ ์ž๋ฃŒ๊ตฌ์กฐ๋‹ค.

3.1 ์„ ์–ธ๊ณผ ์ดˆ๊ธฐํ™”

// ๋ฆฌํ„ฐ๋Ÿด
m := map[string]int{
    "alice": 90,
    "bob":   85,
}
 
// make๋กœ ๋นˆ ๋งต ์ƒ์„ฑ
scores := make(map[string]int)
# Python
m = {"alice": 90, "bob": 85}
scores = {}

3.2 ์ฝ๊ธฐ์™€ ์“ฐ๊ธฐ

m["charlie"] = 78    // ์“ฐ๊ธฐ
score := m["alice"]  // ์ฝ๊ธฐ โ€” 90

์—†๋Š” ํ‚ค๋ฅผ ์ฝ์œผ๋ฉด Python์€ KeyError๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค์ง€๋งŒ, Go๋Š” ํ•ด๋‹น ๊ฐ’ ํƒ€์ž…์˜ zero value๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

score := m["unknown"]  // 0 (int์˜ zero value)

์ด ๋™์ž‘ ๋•Œ๋ฌธ์— ํ‚ค๊ฐ€ ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋ ค๋ฉด comma ok ๊ด€์šฉ๊ตฌ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

3.3 comma ok ๊ด€์šฉ๊ตฌ

v, ok := m["key"]
if !ok {
    fmt.Println("key๊ฐ€ ์—†์Œ")
}

Python์—์„œ๋Š” ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.

# Python โ€” ๋ฐฉ๋ฒ• 1: get
v = m.get("key")  # ์—†์œผ๋ฉด None
 
# Python โ€” ๋ฐฉ๋ฒ• 2: in ์—ฐ์‚ฐ์ž
if "key" in m:
    v = m["key"]

Go์˜ comma ok ํŒจํ„ด์€ Python์˜ dict.get()๊ณผ in ๊ฒ€์‚ฌ๋ฅผ ํ•˜๋‚˜๋กœ ํ•ฉ์นœ ํ˜•ํƒœ๋ผ๊ณ  ๋ณด๋ฉด ๋œ๋‹ค.

3.4 ์‚ญ์ œ

// Go
delete(m, "bob")
# Python
del m["bob"]

Go์˜ delete๋Š” ์—†๋Š” ํ‚ค๋ฅผ ์‚ญ์ œํ•ด๋„ panic์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค. Python์˜ del์€ ์—†๋Š” ํ‚ค๋ฉด KeyError๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

3.5 nil ๋งต ์ฃผ์˜

var m map[string]int  // nil ๋งต
fmt.Println(m["key"]) // 0 โ€” ์ฝ๊ธฐ๋Š” ๋œ๋‹ค
m["key"] = 1          // panic: assignment to entry in nil map

nil ๋งต์— ์“ฐ๊ธฐํ•˜๋ฉด panic

nil ๋งต์€ ์ฝ๊ธฐ๋Š” ๊ฐ€๋Šฅํ•˜์ง€๋งŒ ์“ฐ๊ธฐ๋ฅผ ์‹œ๋„ํ•˜๋ฉด ๋Ÿฐํƒ€์ž„ panic์ด ๋ฐœ์ƒํ•œ๋‹ค. ๋ฐ˜๋“œ์‹œ make(map[string]int) ๋˜๋Š” ๋ฆฌํ„ฐ๋Ÿด map[string]int{}๋กœ ์ดˆ๊ธฐํ™”ํ•œ ๋’ค ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.


4. ๊ตฌ์กฐ์ฒด ๋ง›๋ณด๊ธฐ

Go์˜ ๊ตฌ์กฐ์ฒด(struct)๋Š” Python์˜ dataclass์™€ ๋น„์Šทํ•œ ์—ญํ• ์„ ํ•œ๋‹ค. ์—ฌ๋Ÿฌ ํ•„๋“œ๋ฅผ ํ•˜๋‚˜์˜ ํƒ€์ž…์œผ๋กœ ๋ฌถ๋Š”๋‹ค.

4.1 Python dataclass์™€ ๋น„๊ต

# Python
from dataclasses import dataclass
 
@dataclass
class User:
    name: str
    age: int
// Go
type User struct {
    Name string
    Age  int
}

4.2 ์„ ์–ธ๊ณผ ์‚ฌ์šฉ

// var ์„ ์–ธ โ€” ๋ชจ๋“  ํ•„๋“œ๊ฐ€ zero value
var u User
fmt.Println(u.Name)  // "" (๋นˆ ๋ฌธ์ž์—ด)
fmt.Println(u.Age)   // 0
 
// ๋ฆฌํ„ฐ๋Ÿด ์„ ์–ธ
u2 := User{
    Name: "alice",
    Age:  30,
}

Python์—์„œ๋Š” ๊ธฐ๋ณธ๊ฐ’์„ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ๋ฐ˜๋“œ์‹œ ์ธ์ž๋ฅผ ๋„˜๊ฒจ์•ผ ํ•˜์ง€๋งŒ, Go์˜ ๊ตฌ์กฐ์ฒด๋Š” ์„ ์–ธ๋งŒ ํ•˜๋ฉด ๋ชจ๋“  ํ•„๋“œ๊ฐ€ zero value๋กœ ์ดˆ๊ธฐํ™”๋œ๋‹ค.

4.3 ์ต๋ช… ๊ตฌ์กฐ์ฒด

์ผํšŒ์„ฑ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฌถ๊ณ  ์‹ถ์„ ๋•Œ ํƒ€์ž… ์ด๋ฆ„ ์—†์ด ๊ตฌ์กฐ์ฒด๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

person := struct {
    Name string
    Age  int
}{
    Name: "bob",
    Age:  25,
}

JSON ๋ณ€ํ™˜์ด๋‚˜ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์—์„œ ๊ฐ„๋‹จํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์ž„์‹œ๋กœ ๋‹ด์„ ๋•Œ ์œ ์šฉํ•˜๋‹ค.

4.4 ๊ตฌ์กฐ์ฒด ๋น„๊ต์™€ ๋ณ€ํ™˜

๋น„๊ต

๊ตฌ์กฐ์ฒด๋Š” ๋ชจ๋“  ํ•„๋“œ๊ฐ€ ๋น„๊ต ๊ฐ€๋Šฅํ•œ ํƒ€์ž…(์ˆซ์ž, ๋ฌธ์ž์—ด, bool ๋“ฑ)์œผ๋กœ๋งŒ ์ด๋ฃจ์–ด์ ธ ์žˆ์œผ๋ฉด ==๋กœ ์ง์ ‘ ๋น„๊ตํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ฐ™์€ ํƒ€์ž…์ด๊ณ  ๋ชจ๋“  ํ•„๋“œ ๊ฐ’์ด ๊ฐ™์œผ๋ฉด true๋‹ค.

type Point struct {
    X int
    Y int
}
 
a := Point{1, 2}
b := Point{1, 2}
c := Point{3, 4}
 
fmt.Println(a == b)  // true โ€” ๋ชจ๋“  ํ•„๋“œ๊ฐ€ ๊ฐ™์Œ
fmt.Println(a == c)  // false

๋‹จ, ์Šฌ๋ผ์ด์Šค๋‚˜ ๋งต ๊ฐ™์€ ๋น„๊ต ๋ถˆ๊ฐ€๋Šฅํ•œ ํ•„๋“œ๊ฐ€ ๋“ค์–ด์žˆ์œผ๋ฉด ==๋ฅผ ์“ธ ์ˆ˜ ์—†๊ณ  ์ปดํŒŒ์ผ ์—๋Ÿฌ๊ฐ€ ๋‚œ๋‹ค. ์ด ๊ฒฝ์šฐ๋Š” reflect.DeepEqual ๊ฐ™์€ ๋ณ„๋„ ๋ฐฉ๋ฒ•์„ ์จ์•ผ ํ•œ๋‹ค.

Python์—์„œ๋Š” @dataclass๊ฐ€ __eq__๋ฅผ ์ž๋™ ์ƒ์„ฑํ•ด์„œ ํ•„๋“œ ๊ฐ’์œผ๋กœ ๋น„๊ตํ•ด์ค€๋‹ค. Go์˜ ๊ตฌ์กฐ์ฒด ==๋„ ๊ฒฐ๊ณผ์ ์œผ๋กœ ๋น„์Šทํ•˜์ง€๋งŒ, ์–ธ์–ด ์ฐจ์›์—์„œ ๊ธฐ๋ณธ ์ œ๊ณต๋œ๋‹ค๋Š” ์ ์ด ๋‹ค๋ฅด๋‹ค.

# Python โ€” dataclass๋Š” ๊ฐ’ ๋น„๊ต๋ฅผ ์ž๋™ ์ง€์›
a = Point(1, 2)
b = Point(1, 2)
print(a == b)  # True

๋ณ€ํ™˜

ํƒ€์ž…์ด ๋‹ค๋ฅธ ๋‘ ๊ตฌ์กฐ์ฒด๋Š” ์„œ๋กœ ๋น„๊ตํ•  ์ˆ˜ ์—†๋‹ค. ํ•˜์ง€๋งŒ ํ•„๋“œ์˜ ์ด๋ฆ„, ์ˆœ์„œ, ํƒ€์ž…์ด ๋ชจ๋‘ ๊ฐ™๋‹ค๋ฉด ๋ช…์‹œ์  ํƒ€์ž… ๋ณ€ํ™˜์€ ๊ฐ€๋Šฅํ•˜๋‹ค.

type Point struct {
    X int
    Y int
}
 
type Coord struct {
    X int
    Y int
}
 
p := Point{1, 2}
// fmt.Println(p == Coord{1, 2})  // ์ปดํŒŒ์ผ ์—๋Ÿฌ: ํƒ€์ž…์ด ๋‹ค๋ฆ„
 
c := Coord(p)   // OK โ€” ํ•„๋“œ ์ด๋ฆ„/์ˆœ์„œ/ํƒ€์ž…์ด ๊ฐ™์•„์„œ ๋ณ€ํ™˜ ๊ฐ€๋Šฅ
fmt.Println(c)  // {1 2}

ํ•„๋“œ ๊ตฌ์„ฑ์ด ํ•˜๋‚˜๋ผ๋„ ๋‹ค๋ฅด๋ฉด(์ด๋ฆ„, ์ˆœ์„œ, ํƒ€์ž… ์ค‘ ํ•˜๋‚˜๋ผ๋„) ๋ณ€ํ™˜์ด ์•ˆ ๋œ๋‹ค.

type Named struct {
    X int
    Y int
    Label string  // ํ•„๋“œ๊ฐ€ ํ•˜๋‚˜ ๋” ์žˆ์Œ
}
 
// c := Named(p)  // ์ปดํŒŒ์ผ ์—๋Ÿฌ: ํ•„๋“œ ๊ตฌ์„ฑ์ด ๋‹ค๋ฆ„

๋น„๊ต vs ๋ณ€ํ™˜ ์ •๋ฆฌ

  • ๋น„๊ต(==) : ๊ฐ™์€ ํƒ€์ž…๋ผ๋ฆฌ๋งŒ ๊ฐ€๋Šฅ, ๋ชจ๋“  ํ•„๋“œ ๊ฐ’์ด ๊ฐ™์œผ๋ฉด true
  • ๋ณ€ํ™˜ : ํƒ€์ž…์ด ๋‹ฌ๋ผ๋„ ํ•„๋“œ์˜ ์ด๋ฆ„/์ˆœ์„œ/ํƒ€์ž…์ด ์™„์ „ํžˆ ๊ฐ™์œผ๋ฉด ๋ช…์‹œ์  ๋ณ€ํ™˜ ๊ฐ€๋Šฅ
  • ์Šฌ๋ผ์ด์Šคยท๋งต ํ•„๋“œ๊ฐ€ ์žˆ์œผ๋ฉด == ๋น„๊ต ๋ถˆ๊ฐ€ (reflect.DeepEqual ์‚ฌ์šฉ)