Alert

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

TL;DR

  • ์ธํ„ฐํŽ˜์ด์Šค๋Š” โ€œ์ด ๋™์ž‘์„ ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹คโ€๋Š” contract์ด๊ณ , Python์˜ ๋• ํƒ€์ดํ•‘ยทtyping.Protocol๊ณผ ๊ฐ™์€ ๋ฐœ์ƒ
  • ๊ตฌ์ฒด ํƒ€์ž…์€ โ€œ๋ฌด์—‡์ธ์ง€โ€๊ฐ€ ์ •ํ•ด์ ธ ๊ฐ’ ์ƒ์„ฑ์ด ๊ฐ€๋Šฅํ•˜๊ณ , ์ธํ„ฐํŽ˜์ด์Šค(์ถ”์ƒ ํƒ€์ž…)๋Š” โ€œ๋ฌด์—‡์„ ํ•  ์ˆ˜ ์žˆ๋Š”์ง€โ€๋งŒ ๊ทœ์ •
  • Go ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์•”๋ฌต์  ๊ตฌํ˜„์ด๋ผ ๋ฉ”์„œ๋“œ๋งŒ ๊ฐ–์ถ”๋ฉด ์„ ์–ธ ์—†์ด ์ž๋™์œผ๋กœ ๋งŒ์กฑ๋จ โ€” ์ด๊ฒŒ ๋””์ปคํ”Œ๋ง์˜ ํ•ต์‹ฌ
  • ๊ด€์šฉ๊ตฌ โ€œaccept interfaces, return structsโ€: ์ž…๋ ฅ์€ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ์œ ์—ฐํ•˜๊ฒŒ, ์ถœ๋ ฅ์€ ๊ตฌ์ฒด ํƒ€์ž…์œผ๋กœ ๋ช…ํ™•ํ•˜๊ฒŒ
  • ๋นˆ ์ธํ„ฐํŽ˜์ด์Šค any๋Š” ๋ชจ๋“  ๊ฐ’์„ ๋‹ด์ง€๋งŒ ๋‚จ์šฉ์€ ๊ธˆ๋ฌผ์ด๊ณ , ๊บผ๋‚ผ ๋•Œ๋Š” ํƒ€์ž… ๋‹จ์–ธ(comma-ok)ยทํƒ€์ž… ์Šค์œ„์น˜๋ฅผ ์‚ฌ์šฉ

์ฒ˜์Œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ฐฐ์šฐ๋ฉด ๋Œ€๋ถ€๋ถ„ ๊ฐ™์€ ๋ฒฝ์— ๋ถ€๋”ชํžŒ๋‹ค. ๋ฌธ๋ฒ•์€ ์•Œ๊ฒ ๋Š”๋ฐ โ€œ์ด๊ฑธ ๋„๋Œ€์ฒด ์™œ ์“ฐ๋Š”์ง€โ€๊ฐ€ ์•ˆ ์žกํžŒ๋‹ค. ๊ตฌ์กฐ์ฒด๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด๋Š”๋‹ค๋Š” ๊ฒŒ ์ง๊ด€์ ์ธ๋ฐ, ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋ฐ์ดํ„ฐ๋„ ์—†๊ณ  ๊ฐ’์„ ๋งŒ๋“ค ์ˆ˜๋„ ์—†๋Š” ๋นˆ ๊ป๋ฐ๊ธฐ์ฒ˜๋Ÿผ ๋ณด์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์ด ๊ธ€์€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ โ€œcontract(๊ณ„์•ฝ)โ€œ๋ผ๋Š” ํ•œ ์ค„๋กœ ์žก๊ณ  ์ถœ๋ฐœํ•œ๋‹ค. ์†Œํ”„ํŠธ์›จ์–ด์—์„œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ”ํžˆ contract๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค. ์–ด๋–ค ํƒ€์ž…์ด ์ •ํ•ด์ง„ ๋™์ž‘๋“ค์„ ํ•  ์ˆ˜ ์žˆ์œผ๋ฉด, ๊ทธ๊ฒŒ ์ •ํ™•ํžˆ ๋ญ”์ง€๋Š” ๋ชฐ๋ผ๋„ ๊ทธ ๋™์ž‘์— ์˜์กดํ•ด ์ฝ”๋“œ๋ฅผ ์งค ์ˆ˜ ์žˆ๋‹ค๋Š” ์•ฝ์†์ด๋‹ค. Python์„ ์จ์™”๋‹ค๋ฉด ์‚ฌ์‹ค ์ด๋ฏธ ์ด ๋ฐœ์ƒ์„ ๋งค์ผ ์“ฐ๊ณ  ์žˆ๋‹ค. ํŒŒ์ผ์ด๋“  ๋ฆฌ์ŠคํŠธ๋“  for x in something์ด ๋Œ์•„๊ฐ€๋ฉด ๊ทธ๋ƒฅ ์“ฐ๋Š” ๊ทธ ๊ฐ๊ฐ ๋ง์ด๋‹ค. ๊ทธ๋ž˜์„œ Go์˜ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๋ฐ”๋กœ ๋“ค์–ด๊ฐ€์ง€ ์•Š๊ณ , Python์˜ ๋• ํƒ€์ดํ•‘์—์„œ ์ถœ๋ฐœํ•ด ์ฐจ๊ทผ์ฐจ๊ทผ ์—ฐ๊ฒฐํ•œ๋‹ค.


1. ๋จผ์ €: ์‚ฌ์šฉ์ž ์ •์˜ ํƒ€์ž…(type)

์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ดํ•ดํ•˜๋ ค๋ฉด ๋จผ์ € Go์—์„œ โ€œ์ƒˆ ํƒ€์ž…์„ ๋งŒ๋“ ๋‹คโ€๋Š” ๊ฒŒ ๋ฌด์Šจ ๋œป์ธ์ง€ ์•Œ์•„์•ผ ํ•œ๋‹ค. Go๋Š” type ํ‚ค์›Œ๋“œ๋กœ ๊ธฐ์กด ํƒ€์ž…์— ์ด๋ฆ„์„ ๋ถ™์—ฌ ์‚ฌ์šฉ์ž ์ •์˜ ํƒ€์ž…์„ ๋งŒ๋“ ๋‹ค.

๊ฐ€์žฅ ํ”ํ•œ ๊ฑด ๊ตฌ์กฐ์ฒด๋‹ค.

type Person struct {
    Name string
    Age  int
}

์—ฌ๊ธฐ์„œ ๋์ด ์•„๋‹ˆ๋‹ค. ๊ตฌ์กฐ์ฒด๋ฟ ์•„๋‹ˆ๋ผ ๊ธฐ๋ณธ ํƒ€์ž…์ด๋‚˜ ํ•จ์ˆ˜ ํƒ€์ž…์—๋„ ์ด๋ฆ„์„ ๋ถ™์ผ ์ˆ˜ ์žˆ๋‹ค.

type Score int                      // int์— Score๋ผ๋Š” ์ด๋ฆ„์„ ๋ถ™์ž„
type Converter func(string) Score   // ํ•จ์ˆ˜ ์‹œ๊ทธ๋‹ˆ์ฒ˜์—๋„ ์ด๋ฆ„์„ ๋ถ™์ž„

type Score int์€ โ€œ์ •์ˆ˜์ธ๋ฐ, ์˜๋ฏธ์ƒ ์ ์ˆ˜โ€๋ผ๋Š” ์ƒˆ ํƒ€์ž…์„ ๋งŒ๋“  ๊ฒƒ์ด๋‹ค. ๋‚ด๋ถ€ ํ‘œํ˜„์€ int๊ณผ ๊ฐ™์ง€๋งŒ Go๋Š” ์ด ๋‘˜์„ ๋‹ค๋ฅธ ํƒ€์ž…์œผ๋กœ ์ทจ๊ธ‰ํ•œ๋‹ค. type Converter func(string) Score๋Š” โ€œ๋ฌธ์ž์—ด์„ ๋ฐ›์•„ Score๋ฅผ ๋Œ๋ ค์ฃผ๋Š” ํ•จ์ˆ˜โ€๋ผ๋Š” ํƒ€์ž…์— ์ด๋ฆ„์„ ๋ถ™์ธ ๊ฒƒ์ด๋‹ค(05ํŽธ์—์„œ ํ•จ์ˆ˜๊ฐ€ ์ผ๊ธ‰ ๊ฐ’์ด๋ผ๋Š” ๊ฑธ ๋‹ค๋ค˜๋‹ค).

Python์— ๋น„์œ ํ•˜๋ฉด class Person:์œผ๋กœ ํด๋ž˜์Šค๋ฅผ ์ •์˜ํ•˜๋Š” ๊ฒƒ, ํ˜น์€ Score = int์ฒ˜๋Ÿผ ํƒ€์ž… ๋ณ„์นญ์„ ๋งŒ๋“œ๋Š” ๊ฒƒ๊ณผ ๋น„์Šทํ•œ ์ž๋ฆฌ์— ์žˆ๋‹ค. ๋‹ค๋งŒ Python์˜ ๋‹จ์ˆœ ๋ณ„์นญ(Score = int)์€ int๊ณผ ๊ฐ™์€ ํƒ€์ž…์œผ๋กœ ์ทจ๊ธ‰๋˜๋Š” ๋ฐ˜๋ฉด, Go์˜ type Score int์€ ์ง„์งœ ๋ณ„๊ฐœ์˜ ํƒ€์ž…์ด๋‹ค. Python์—์„œ ์ด๋ ‡๊ฒŒ ๊ตฌ๋ถ„๋˜๋Š” ๋ณ„๊ฐœ ํƒ€์ž…์„ ๋งŒ๋“ค๋ ค๋ฉด NewType์„ ์จ์•ผ ํ•˜๋Š”๋ฐ, ์ž์„ธํ•œ ๊ฑด Python typing ๋…ธํŠธ์— ์ •๋ฆฌ๋ผ ์žˆ๋‹ค.

์™œ ๊ตณ์ด ์ƒˆ ํƒ€์ž…์„ ๋งŒ๋“œ๋‚˜

int์„ ๊ทธ๋ƒฅ ์“ฐ๋ฉด ๋  ๊ฒƒ ๊ฐ™์€๋ฐ type Score int์„ ๋งŒ๋“œ๋Š” ์ด์œ ๋Š”, ์˜๋ฏธ๊ฐ€ ๋‹ค๋ฅธ ๊ฐ’์„ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ๊ตฌ๋ถ„ํ•ด์ฃผ๊ธธ ๋ฐ”๋ผ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. Score์™€ ์ผ๋ฐ˜ int์„ ์‹ค์ˆ˜๋กœ ์„ž์–ด ์“ฐ๋ฉด ์ปดํŒŒ์ผ ์—๋Ÿฌ๊ฐ€ ๋‚œ๋‹ค. ๋” ์ค‘์š”ํ•œ ๊ฑด, ์ด๋ ‡๊ฒŒ ๋งŒ๋“  ํƒ€์ž…์— ๋ฉ”์„œ๋“œ๋ฅผ ๋ถ™์ผ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด๋‹ค. ๋‹ค์Œ ์ ˆ์˜ ์ฃผ์ œ๋‹ค.


2. ๋ฉ”์„œ๋“œ(method) โ€” ํƒ€์ž…์— ๋ถ™๋Š” ํ•จ์ˆ˜

๋ฉ”์„œ๋“œ๋Š” ํŠน์ • ํƒ€์ž…์— ๋ฌถ์ธ ํ•จ์ˆ˜๋‹ค. ์ผ๋ฐ˜ ํ•จ์ˆ˜์™€ ๊ฑฐ์˜ ๊ฐ™์ง€๋งŒ, ํ•จ์ˆ˜ ์ด๋ฆ„ ์•ž์— **๋ฆฌ์‹œ๋ฒ„(receiver)**๊ฐ€ ํ•˜๋‚˜ ๋ถ™๋Š”๋‹ค.

type Person struct {
    Name string
    Age  int
}
 
// (p Person) ๋ถ€๋ถ„์ด ๋ฆฌ์‹œ๋ฒ„
func (p Person) Greet() string {
    return "์•ˆ๋…•ํ•˜์„ธ์š”, " + p.Name + "์ž…๋‹ˆ๋‹ค"
}
 
func main() {
    p := Person{Name: "Alice", Age: 30}
    fmt.Println(p.Greet())  // ์•ˆ๋…•ํ•˜์„ธ์š”, Alice์ž…๋‹ˆ๋‹ค
}

func (p Person) Greet()์—์„œ (p Person)์ด ๋ฆฌ์‹œ๋ฒ„๋‹ค. โ€œ์ด ํ•จ์ˆ˜๋Š” Person ํƒ€์ž…์— ๋ถ™๋Š”๋‹คโ€๋Š” ์„ ์–ธ์ด๊ณ , ํ•จ์ˆ˜ ์•ˆ์—์„œ p๋กœ ๊ทธ ์ธ์Šคํ„ด์Šค์— ์ ‘๊ทผํ•œ๋‹ค. Python์˜ self์™€ ์ •ํ™•ํžˆ ๊ฐ™์€ ์—ญํ• ์ด๋‹ค.

# Python
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
 
    def greet(self):
        return f"์•ˆ๋…•ํ•˜์„ธ์š”, {self.name}์ž…๋‹ˆ๋‹ค"

์ฐจ์ด๋ผ๋ฉด Python์€ self๋ฅผ ๋ฉ”์„œ๋“œ ์•ˆ์—์„œ ์ฒซ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์ง€๋งŒ, Go๋Š” ํ•จ์ˆ˜ ์ด๋ฆ„ ์•ž์— ๋ฆฌ์‹œ๋ฒ„๋ฅผ ๋”ฐ๋กœ ๋‘”๋‹ค๋Š” ์ ์ด๋‹ค. ๊ด€๋ก€์ƒ ๋ฆฌ์‹œ๋ฒ„ ๋ณ€์ˆ˜๋ช…์€ ํƒ€์ž…๋ช… ์ฒซ ๊ธ€์ž๋ฅผ ๋”ด ์•ฝ์–ด๋ฅผ ์“ด๋‹ค(Person โ†’ p). ๊ทธ๋ฆฌ๊ณ  ๋ฉ”์„œ๋“œ๋Š” ์—ฐ๊ด€๋œ ํƒ€์ž…๊ณผ ๊ฐ™์€ ํŒจํ‚ค์ง€ ์•ˆ์— ์ •์˜ํ•ด์•ผ ํ•œ๋‹ค.

๊ฐ’ ๋ฆฌ์‹œ๋ฒ„ vs ํฌ์ธํ„ฐ ๋ฆฌ์‹œ๋ฒ„

๋ฆฌ์‹œ๋ฒ„์—๋Š” ๋‘ ์ข…๋ฅ˜๊ฐ€ ์žˆ๋‹ค. ๊ฐ’ ๋ฆฌ์‹œ๋ฒ„ (p Person)์™€ ํฌ์ธํ„ฐ ๋ฆฌ์‹œ๋ฒ„ (p *Person)๋‹ค. ์–ด๋А ์ชฝ์„ ์“ธ์ง€๋Š” ๊ทœ์น™์ด ๋‹จ์ˆœํ•˜๋‹ค.

๋ฆฌ์‹œ๋ฒ„ ์„ ํƒ ๊ทœ์น™

  • ๋ฆฌ์‹œ๋ฒ„๋ฅผ ์ˆ˜์ •ํ•ด์•ผ ํ•˜๋ฉด ํฌ์ธํ„ฐ ๋ฆฌ์‹œ๋ฒ„ (*Person)
  • nil ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜๋ฉด ํฌ์ธํ„ฐ ๋ฆฌ์‹œ๋ฒ„
  • ์ˆ˜์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ๊ฐ’ ๋ฆฌ์‹œ๋ฒ„ (Person)

์ด ๊ทœ์น™์€ 06ํŽธ์˜ call by value์™€ ๋ฐ”๋กœ ์ด์–ด์ง„๋‹ค. Go๋Š” ๊ฐ’์„ ๋ณต์‚ฌํ•ด์„œ ๋„˜๊ธฐ๋ฏ€๋กœ, ๊ฐ’ ๋ฆฌ์‹œ๋ฒ„๋Š” ์ธ์Šคํ„ด์Šค์˜ ๋ณต์‚ฌ๋ณธ์„ ๋ฐ›๋Š”๋‹ค. ๋ณต์‚ฌ๋ณธ์„ ์ˆ˜์ •ํ•ด๋ดค์ž ์›๋ณธ์€ ์•ˆ ๋ฐ”๋€๋‹ค. ์›๋ณธ์„ ๋ฐ”๊พธ๋ ค๋ฉด ์ฃผ์†Œ๋ฅผ ๋ฐ›์•„์•ผ ํ•˜๊ณ , ๊ทธ๊ฒŒ ํฌ์ธํ„ฐ ๋ฆฌ์‹œ๋ฒ„๋‹ค.

// ๊ฐ’ ๋ฆฌ์‹œ๋ฒ„ โ€” ๋ณต์‚ฌ๋ณธ์„ ๋ฐ›์œผ๋ฏ€๋กœ ์›๋ณธ์ด ์•ˆ ๋ฐ”๋€œ
func (p Person) GrowUpWrong() {
    p.Age++   // ๋ณต์‚ฌ๋ณธ์˜ Age๋งŒ ์ฆ๊ฐ€. ์›๋ณธ ๊ทธ๋Œ€๋กœ
}
 
// ํฌ์ธํ„ฐ ๋ฆฌ์‹œ๋ฒ„ โ€” ์ฃผ์†Œ๋ฅผ ๋ฐ›์œผ๋ฏ€๋กœ ์›๋ณธ์ด ๋ฐ”๋€œ
func (p *Person) GrowUp() {
    p.Age++   // ์›๋ณธ์˜ Age๊ฐ€ ์ฆ๊ฐ€
}
 
func main() {
    p := Person{Name: "Alice", Age: 30}
 
    p.GrowUpWrong()
    fmt.Println(p.Age)  // 30 โ€” ์•ˆ ๋ฐ”๋€œ
 
    p.GrowUp()
    fmt.Println(p.Age)  // 31 โ€” ๋ฐ”๋€œ
}

p.GrowUp()์„ ๋ณด๋ฉด p๋Š” ํฌ์ธํ„ฐ๊ฐ€ ์•„๋‹Œ ๊ฐ’์ธ๋ฐ๋„ ํฌ์ธํ„ฐ ๋ฆฌ์‹œ๋ฒ„ ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค. Go๊ฐ€ (&p).GrowUp()์œผ๋กœ ์•Œ์•„์„œ ์ฃผ์†Œ๋ฅผ ์žก์•„์ฃผ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋ฐ˜๋Œ€๋กœ ํฌ์ธํ„ฐ ์ธ์Šคํ„ด์Šค(*Person)๋Š” ๊ฐ’ ๋ฆฌ์‹œ๋ฒ„ ๋ฉ”์„œ๋“œ์™€ ํฌ์ธํ„ฐ ๋ฆฌ์‹œ๋ฒ„ ๋ฉ”์„œ๋“œ๋ฅผ ๋‘˜ ๋‹ค ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค.

String() ๋ฉ”์„œ๋“œ โ€” ๊ฐ€์žฅ ์ž์ฃผ ์“ฐ๋Š” ์˜ˆ

ํƒ€์ž…์— String() string ๋ฉ”์„œ๋“œ๋ฅผ ๋ถ™์ด๋ฉด, fmt.Println์œผ๋กœ ์ถœ๋ ฅํ•  ๋•Œ ๊ทธ ๋ฉ”์„œ๋“œ์˜ ๊ฒฐ๊ณผ๊ฐ€ ์“ฐ์ธ๋‹ค. Python์˜ __str__๊ณผ ๊ฐ™์€ ์—ญํ• ์ด๋‹ค.

type Score int
 
func (s Score) String() string {
    return fmt.Sprintf("%d์ ", int(s))
}
 
func main() {
    var s Score = 95
    fmt.Println(s)  // 95์  โ€” ๊ธฐ๋ณธ ์ถœ๋ ฅ ๋Œ€์‹  String()์˜ ๊ฒฐ๊ณผ
}
# Python์˜ __str__
class Score:
    def __init__(self, value):
        self.value = value
 
    def __str__(self):
        return f"{self.value}์ "
 
print(Score(95))  # 95์ 

์ด String()์ด ๋ฐ”๋กœ ๋‹ค์Œ์— ๋‚˜์˜ฌ ์ธํ„ฐํŽ˜์ด์Šค ์ด์•ผ๊ธฐ๋กœ ์ด์–ด์ง„๋‹ค. ์‚ฌ์‹ค ์œ„ ์ฝ”๋“œ๋Š” Go์˜ fmt.Stringer๋ผ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ž๊ธฐ๋„ ๋ชจ๋ฅด๊ฒŒ ๋งŒ์กฑ์‹œํ‚จ ๊ฒƒ์ด๋‹ค. ์ด์ œ ๊ทธ๊ฒŒ ๋ฌด์Šจ ๋œป์ธ์ง€ ํ’€์–ด๋ณด์ž.


3. ์ธํ„ฐํŽ˜์ด์Šค๋ž€ ๋ฌด์—‡์ธ๊ฐ€ โ€” ๊ตฌ์ฒด ํƒ€์ž… vs ์ถ”์ƒ ํƒ€์ž…

์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ดํ•ดํ•˜๋Š” ํ•ต์‹ฌ์€ ํƒ€์ž…์„ ๋‘ ์ข…๋ฅ˜๋กœ ๋‚˜๋ˆ  ๋ณด๋Š” ๊ฒƒ์ด๋‹ค. **๊ตฌ์ฒด ํƒ€์ž…(concrete type)**๊ณผ **์ถ”์ƒ ํƒ€์ž…(abstract type)**์ด๋‹ค.

๊ตฌ์ฒด ํƒ€์ž…์€ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์–ด๋–ป๊ฒŒ ํ‘œํ˜„๋˜๋Š”์ง€, ์–ด๋–ค ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด๋Š”์ง€, ์–ด๋–ค ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€์ง€๋Š”์ง€๊ฐ€ ์™„์ „ํžˆ ์ •ํ•ด์ง„ ํƒ€์ž…์ด๋‹ค. โ€œ์‹ค์ฒด๊ฐ€ ์žˆ๋Š”โ€ ํƒ€์ž…์ด๋ผ๊ณ  ๋ณด๋ฉด ๋œ๋‹ค. int, string, ๊ตฌ์กฐ์ฒด, ์Šฌ๋ผ์ด์Šค, ๋งต, ํฌ์ธํ„ฐ๊ฐ€ ์ „๋ถ€ ๊ตฌ์ฒด ํƒ€์ž…์ด๋‹ค. ์ •ํ•ด์ง„ ๊ฒŒ ๋‹ค ์žˆ์œผ๋‹ˆ ๋ฐ”๋กœ ๊ฐ’์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

p := Person{Name: "Alice", Age: 30}  // ๊ตฌ์ฒด ํƒ€์ž… โ€” ๋ฐ”๋กœ ๊ฐ’ ์ƒ์„ฑ ๊ฐ€๋Šฅ
n := 42                              // int๋„ ๊ตฌ์ฒด ํƒ€์ž…

์ถ”์ƒ ํƒ€์ž…์€ ๋ฐ˜๋Œ€๋‹ค. โ€œ๋ฌด์—‡์ธ์ง€(๋ฐ์ดํ„ฐ ๊ตฌ์กฐ)โ€œ๋Š” ๋งํ•˜์ง€ ์•Š๊ณ , โ€œ๋ฌด์—‡์„ ํ•  ์ˆ˜ ์žˆ๋Š”์ง€(๋ฉ”์„œ๋“œ ์ง‘ํ•ฉ)โ€œ๋งŒ ๊ทœ์ •ํ•œ๋‹ค. Go์—์„œ ์œ ์ผํ•œ ์ถ”์ƒ ํƒ€์ž…์ด ๋ฐ”๋กœ ์ธํ„ฐํŽ˜์ด์Šค๋‹ค. ์ธํ„ฐํŽ˜์ด์Šค ์„ ์–ธ์€ ๋ฉ”์„œ๋“œ ๋ชฉ๋ก๋งŒ ๋‚˜์—ดํ•œ๋‹ค.

type Stringer interface {
    String() string
}

์ด Stringer๋Š” โ€œString() string ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€์ง„ ๋ฌด์–ธ๊ฐ€โ€๋ผ๋Š” contract์ผ ๋ฟ, ๊ทธ ์ž์ฒด๋กœ๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ์—†๋‹ค. ๊ทธ๋ž˜์„œ Stringer{}์ฒ˜๋Ÿผ ๊ฐ’์„ ์ง์ ‘ ๋งŒ๋“ค ์ˆ˜ ์—†๋‹ค. ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๊ตฌ์ฒด ํƒ€์ž…์„ ๋‹ด๋Š” ๊ทธ๋ฆ‡์ด์ง€, ์Šค์Šค๋กœ ์‹ค์ฒด๊ฐ€ ๋˜์ง€๋Š” ๋ชปํ•œ๋‹ค.

์‹ค์ƒํ™œ ๋น„์œ : USB ํฌํŠธ

USB ํฌํŠธ๋ฅผ ๋– ์˜ฌ๋ ค๋ณด์ž. ํฌํŠธ๋Š” โ€œ์ด๋Ÿฐ ๋ชจ์–‘๊ณผ ๊ทœ๊ฒฉ์„ ๊ฐ–์ถ”๋ฉด ๊ฝ‚ํžŒ๋‹คโ€๋Š” ์•ฝ์†๋งŒ ์ •์˜ํ•œ๋‹ค. ๋งˆ์šฐ์Šค๋“  ํ‚ค๋ณด๋“œ๋“  ์™ธ์žฅํ•˜๋“œ๋“ , ๊ทธ ๊ทœ๊ฒฉ์— ๋งž๋Š” ๋ชจ์–‘๋งŒ ๊ฐ–์ถ”๋ฉด ์–ด๋–ค ๊ธฐ๊ธฐ๋“  ๊ฝ‚ํžŒ๋‹ค. ํฌํŠธ ์ž…์žฅ์—์„œ๋Š” ๊ฝ‚ํžŒ ๊ฒŒ ์ •ํ™•ํžˆ ๋ฌด์Šจ ๊ธฐ๊ธฐ์ธ์ง€ ๋ชฐ๋ผ๋„ ๋œ๋‹ค. ๊ทœ๊ฒฉ๋งŒ ๋งž์œผ๋ฉด ๊ทธ๋งŒ์ด๋‹ค.

์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์ •ํ™•ํžˆ ์ด๋ ‡๋‹ค. โ€œ์ด ๋ฉ”์„œ๋“œ๋“ค์„ ๊ฐ–์ถฐ๋ผโ€๊ฐ€ USB ๊ทœ๊ฒฉ์ด๊ณ , ๊ทธ ๋ฉ”์„œ๋“œ๋“ค์„ ๊ฐ–์ถ˜ ํƒ€์ž…์ด๋ฉด ์–ด๋–ค ๊ตฌ์ฒด ํƒ€์ž…์ด๋“  ๊ทธ ์ธํ„ฐํŽ˜์ด์Šค ์ž๋ฆฌ์— ๊ฝ‚ํžŒ๋‹ค. ๋ฐ›๋Š” ์ชฝ์€ ๊ฝ‚ํžŒ ๊ฒŒ Person์ธ์ง€ Score์ธ์ง€ ๋ชฐ๋ผ๋„, ์•ฝ์†๋œ ๋ฉ”์„œ๋“œ๋งŒ ํ˜ธ์ถœํ•˜๋ฉด ๋œ๋‹ค.

์ธํ„ฐํŽ˜์ด์Šค ๊ฐ’ ์•ˆ์—๋Š” ํ•ญ์ƒ ๊ตฌ์ฒด ํƒ€์ž…์ด ๋“ค์–ด์žˆ๋‹ค

์ธํ„ฐํŽ˜์ด์Šค๋Š” ์Šค์Šค๋กœ ๊ฐ’์„ ๋ชป ๋งŒ๋“ ๋‹ค๊ณ  ํ–ˆ์ง€๋งŒ, ์ธํ„ฐํŽ˜์ด์Šค ๋ณ€์ˆ˜๋Š” ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค. ๋‹จ, ๊ทธ ๋ณ€์ˆ˜ ์•ˆ์—๋Š” ๋Ÿฐํƒ€์ž„์— ํ•ญ์ƒ ์–ด๋–ค ๊ตฌ์ฒด ํƒ€์ž…์˜ ๊ฐ’์ด ๋“ค์–ด๊ฐ€ ์žˆ๋‹ค.

var s Stringer        // ์ธํ„ฐํŽ˜์ด์Šค ๋ณ€์ˆ˜. ์ง€๊ธˆ์€ nil
s = Score(95)         // ์•ˆ์— ๊ตฌ์ฒด ํƒ€์ž… Score(95)๊ฐ€ ๋‹ด๊น€
fmt.Println(s.String())  // 95์ 

s๋Š” Stringer ํƒ€์ž…์ด์ง€๋งŒ, ์‹ค์ œ๋กœ ์•ˆ์— ๋“  ๊ฑด Score(95)๋ผ๋Š” ๊ตฌ์ฒด ํƒ€์ž… ๊ฐ’์ด๋‹ค. ์ด โ€œ์•ˆ์— ๋“  ๊ตฌ์ฒด ํƒ€์ž…โ€์„ ๋‹ค์‹œ ๊บผ๋‚ด๋Š” ๋ฐฉ๋ฒ•(ํƒ€์ž… ๋‹จ์–ธ)์€ 7๋ฒˆ์—์„œ ๋‹ค๋ฃฌ๋‹ค.

PythonยทC++๋กœ ๋น„์œ 

์ด ๊ตฌ๋„๋Š” ๋‹ค๋ฅธ ์–ธ์–ด์—๋„ ๋˜‘๊ฐ™์ด ์žˆ๋‹ค.

๊ตฌ์ฒด ํƒ€์ž… (์ธ์Šคํ„ด์Šคํ™” ๊ฐ€๋Šฅ)์ถ”์ƒ ํƒ€์ž… (์ธ์Šคํ„ด์Šคํ™” ๋ถˆ๊ฐ€)
Pythonlist, dict, ์‚ฌ์šฉ์ž classabc.ABC, typing.Protocol, collections.abc.Sequence
C++๊ตฌ์ฒด ํด๋ž˜์Šค์ˆœ์ˆ˜ ๊ฐ€์ƒํ•จ์ˆ˜๋ฅผ ๊ฐ€์ง„ ์ถ”์ƒ ํด๋ž˜์Šค
Goint, ๊ตฌ์กฐ์ฒด, ์Šฌ๋ผ์ด์Šค, ๋งต, ํฌ์ธํ„ฐ์ธํ„ฐํŽ˜์ด์Šค

Python์—์„œ Sequence๋ฅผ ์ง์ ‘ ์ธ์Šคํ„ด์Šคํ™”ํ•  ์ˆ˜ ์—†๊ณ  list๋งŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ๊ฒƒ, C++์—์„œ ์ˆœ์ˆ˜ ๊ฐ€์ƒํ•จ์ˆ˜๋ฅผ ๊ฐ€์ง„ ์ถ”์ƒ ํด๋ž˜์Šค๋กœ๋Š” ๊ฐ์ฒด๋ฅผ ๋ชป ๋งŒ๋“œ๋Š” ๊ฒƒ๊ณผ ์ •ํ™•ํžˆ ๊ฐ™์€ ๊ตฌ๋ถ„์ด๋‹ค. ๋‚˜์ค‘์— ๋‚˜์˜ฌ ๊ด€์šฉ๊ตฌ โ€œaccept interfaces, return structsโ€๋„ ๊ฒฐ๊ตญ ์ด ๊ตฌ์ฒด/์ถ”์ƒ ๊ตฌ๋ถ„์—์„œ ๋‚˜์˜จ ๋ง์ด๋‹ค.


4. Go ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ง„์งœ ํŠน์ง•: ์•”๋ฌต์  ๊ตฌํ˜„

์—ฌ๊ธฐ๊ฐ€ Go ์ธํ„ฐํŽ˜์ด์Šค์—์„œ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ์ง€์ ์ด๋‹ค. Go๋Š” ์•”๋ฌต์ (implicit) ๊ตฌํ˜„์„ ์“ด๋‹ค. ์ •ํ•ด์ง„ ๋ฉ”์„œ๋“œ๋ฅผ ๋‹ค ๊ฐ–์ถ”๊ธฐ๋งŒ ํ•˜๋ฉด, ์•„๋ฌด ์„ ์–ธ ์—†์ด๋„ ์ž๋™์œผ๋กœ ๊ทธ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋งŒ์กฑํ•œ๋‹ค.

Java๋ฅผ ๋– ์˜ฌ๋ ค๋ณด๋ฉด ์ฐจ์ด๊ฐ€ ๋ถ„๋ช…ํ•˜๋‹ค. Java๋Š” ๋ช…์‹œ์ ์œผ๋กœ ์„ ์–ธํ•ด์•ผ ํ•œ๋‹ค.

// Java โ€” implements๋ฅผ ๋ช…์‹œํ•ด์•ผ ํ•œ๋‹ค
class Score implements Stringer {
    public String toString() { ... }
}

Go๋Š” implements ๊ฐ™์€ ํ‚ค์›Œ๋“œ๊ฐ€ ์—†๋‹ค. ๊ทธ๋ƒฅ ๋ฉ”์„œ๋“œ๋งŒ ๋งž์œผ๋ฉด ๋์ด๋‹ค.

type Stringer interface {
    String() string
}
 
type Score int
 
// "implements Stringer" ๊ฐ™์€ ์„ ์–ธ์ด ์ „ํ˜€ ์—†๋‹ค
func (s Score) String() string {
    return fmt.Sprintf("%d์ ", int(s))
}
 
// ๊ทธ๋Ÿฐ๋ฐ๋„ Score๋Š” Stringer๋ฅผ ์ž๋™์œผ๋กœ ๋งŒ์กฑํ•œ๋‹ค
var x Stringer = Score(95)  // ๋ฌธ์ œ์—†์ด ์ปดํŒŒ์ผ๋จ

Score๋Š” ์–ด๋””์—๋„ โ€œ๋‚˜๋Š” Stringer๋‹คโ€๋ผ๊ณ  ์“ฐ์ง€ ์•Š์•˜๋‹ค. ๊ทธ์ € String() string ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€์กŒ์„ ๋ฟ์ด๋‹ค. ๊ทธ๊ฒƒ๋งŒ์œผ๋กœ Stringer๊ฐ€ ์š”๊ตฌํ•˜๋Š” ๋™์ž‘์„ ์ถฉ์กฑํ•˜๋‹ˆ, Go๋Š” ์ž๋™์œผ๋กœ Score๋ฅผ Stringer๋กœ ๋ฐ›์•„๋“ค์ธ๋‹ค.

Python ๋• ํƒ€์ดํ•‘๊ณผ ๊ฐ™์€ ๋ฐœ์ƒ

Python์„ ์จ์™”๋‹ค๋ฉด ์ด๊ฒŒ ๋‚ฏ์„ค์ง€ ์•Š๋‹ค. Python์˜ ๋• ํƒ€์ดํ•‘์ด ์ •ํ™•ํžˆ ์ด ๋ฐœ์ƒ์ด๋‹ค. โ€œ์˜ค๋ฆฌ์ฒ˜๋Ÿผ ๊ฑท๊ณ  ์˜ค๋ฆฌ์ฒ˜๋Ÿผ ์šธ๋ฉด ๊ทธ๊ฑด ์˜ค๋ฆฌ๋‹ค.โ€ ๋ฌด์Šจ ํƒ€์ž…์ธ์ง€ ๋ฏธ๋ฆฌ ์„ ์–ธํ•˜์ง€ ์•Š๊ณ , ํ•„์š”ํ•œ ๋ฉ”์„œ๋“œ๋งŒ ์žˆ์œผ๋ฉด ๊ทธ๋ƒฅ ์“ด๋‹ค.

# Python ๋• ํƒ€์ดํ•‘ โ€” ์ƒ์† ์„ ์–ธ ์—†์ด ๊ทธ๋ƒฅ ๋ฉ”์„œ๋“œ๋งŒ ์žˆ์œผ๋ฉด ๋™์ž‘
class Score:
    def __str__(self):
        return f"{self.value}์ "
 
# print๋Š” Score๊ฐ€ ๋ฌด์Šจ ํƒ€์ž…์ธ์ง€ ์•ˆ ๋”ฐ์ง„๋‹ค. __str__๋งŒ ์žˆ์œผ๋ฉด ์“ด๋‹ค

Python 3.8๋ถ€ํ„ฐ๋Š” ์ด๊ฑธ ์ข€ ๋” ์ •์ ์œผ๋กœ ํ‘œํ˜„ํ•˜๋Š” typing.Protocol์ด ์ƒ๊ฒผ๋‹ค. ๋ช…์‹œ์  ์ƒ์† ์—†์ด โ€œ์ด๋Ÿฐ ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€์ง„ ๋ฌด์—‡์ด๋“ โ€ ๋ฐ›๋Š”๋‹ค๊ณ  ํƒ€์ž… ํžŒํŠธ๋กœ ์ ์„ ์ˆ˜ ์žˆ๋‹ค.

from typing import Protocol
 
class Stringer(Protocol):
    def __str__(self) -> str: ...
 
def show(x: Stringer) -> None:
    print(x)   # __str__๋งŒ ์žˆ์œผ๋ฉด ์–ด๋–ค ํƒ€์ž…์ด๋“  ๋ฐ›์Œ

typing.Protocol์€ ์‚ฌ์‹ค์ƒ Go ์ธํ„ฐํŽ˜์ด์Šค์˜ Python ๋ฒ„์ „์ด๋‹ค. Go๊ฐ€ ์ฒ˜์Œ๋ถ€ํ„ฐ ์–ธ์–ด ์ฐจ์›์—์„œ ํ–ˆ๋˜ ๊ฑธ, Python์€ ํƒ€์ž… ํžŒํŠธ๋กœ ๋‚˜์ค‘์— ๋“ค์—ฌ์˜จ ์…ˆ์ด๋‹ค. typing.Protocol์˜ ๋ฌธ๋ฒ•๊ณผ ๊ตฌ์กฐ์  ํƒ€์ดํ•‘(structural typing)์€ Python typing ๋…ธํŠธ์˜ Protocol์—์„œ ๋” ์ž์„ธํžˆ ๋‹ค๋ฃฌ๋‹ค.

์™œ ์ด๊ฒŒ ๋””์ปคํ”Œ๋ง์˜ ํ•ต์‹ฌ์ธ๊ฐ€

์•”๋ฌต์  ๊ตฌํ˜„์ด ์ค‘์š”ํ•œ ์ด์œ ๋Š” ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถ”๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. Score๋ฅผ ์ •์˜ํ•˜๋Š” ์‚ฌ๋žŒ์€ Stringer ์ธํ„ฐํŽ˜์ด์Šค์˜ ์กด์žฌ ์ž์ฒด๋ฅผ ๋ชฐ๋ผ๋„ ๋œ๋‹ค. ๋‚˜์ค‘์— ๋ˆ„๊ตฐ๊ฐ€ Stringer๋ฅผ ๋ฐ›๋Š” ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค๋ฉด, Score๋Š” ์ฝ”๋“œ๋ฅผ ์ „ํ˜€ ์•ˆ ๊ณ ์ณ๋„ ๊ฑฐ๊ธฐ์— ๊ทธ๋ƒฅ ๋“ค์–ด๊ฐ„๋‹ค.

์—ฌ๊ธฐ์„œ Go ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋ฐœ์ƒ ์ „ํ™˜์ด ๋‚˜์˜จ๋‹ค. ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๊ตฌํ˜„ํ•˜๋Š” ์ชฝ์ด ์•„๋‹ˆ๋ผ ์‚ฌ์šฉํ•˜๋Š” ์ชฝ(ํ˜ธ์ถœ์ž)์ด ์ •์˜ํ•œ๋‹ค. Java์—์„œ๋Š” ๋ณดํ†ต ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ œ๊ณต์ž๊ฐ€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ฃผ๊ณ  ์‚ฌ์šฉ์ž๊ฐ€ ๊ตฌํ˜„ํ•˜์ง€๋งŒ, Go์—์„œ๋Š” ๋ฐ˜๋Œ€๊ฐ€ ์ž์—ฐ์Šค๋Ÿฝ๋‹ค. ์–ด๋–ค ํ•จ์ˆ˜๋ฅผ ์งœ๋Š”๋ฐ ์ž…๋ ฅ์ด โ€œRead ๋ฉ”์„œ๋“œ๋งŒ ์žˆ์œผ๋ฉด ๋˜๊ฒ ๋‹คโ€ ์‹ถ์œผ๋ฉด, ํ˜ธ์ถœ์ž๊ฐ€ ์ž๊ธฐ์—๊ฒŒ ํ•„์š”ํ•œ ๋™์ž‘๋งŒ ๋‹ด์€ ์ž‘์€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ทธ ์ž๋ฆฌ์—์„œ ์ •์˜ํ•œ๋‹ค. ๊ตฌํ˜„์ฒด๋Š” ๊ทธ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ชฐ๋ผ๋„ ๋ฉ”์„œ๋“œ๋งŒ ๋งž์œผ๋ฉด ์•Œ์•„์„œ ๋“ค์–ด๋งž๋Š”๋‹ค.

์ด๊ฒŒ โ€œ์•ˆ์ •์ ์ธ ๋• ํƒ€์ดํ•‘โ€์ด๋ผ ๋ถˆ๋ฆฌ๋Š” ์ด์œ ๋‹ค. Python์˜ ๋• ํƒ€์ดํ•‘์€ ๋Ÿฐํƒ€์ž„์— ๋ฉ”์„œ๋“œ๊ฐ€ ์—†์œผ๋ฉด ํ„ฐ์ง€์ง€๋งŒ, Go๋Š” ์ปดํŒŒ์ผ ํƒ€์ž„์— ๋ฉ”์„œ๋“œ๊ฐ€ ๋งž๋Š”์ง€ ๊ฒ€์‚ฌํ•œ๋‹ค. ์œ ์—ฐํ•จ์€ ์œ ์ง€ํ•˜๋˜ ์•ˆ์ „์„ฑ์„ ์–น์€ ๊ฒƒ์ด๋‹ค.


5. ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ธํ„ฐํŽ˜์ด์Šค

์ด๋ก ์€ ์ด์ฏค ํ•˜๊ณ , ์‹ค์ œ๋กœ ๋งค์ผ ์“ฐ๋Š” ํ‘œ์ค€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ณด์ž. Go ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์ž‘์€ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ์งœ์—ฌ ์žˆ๊ณ , ์ด๊ฒŒ ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ์˜ ํ† ๋Œ€๊ฐ€ ๋œ๋‹ค.

fmt.Stringer

์•ž์—์„œ ๋ณธ ๊ทธ ์ธํ„ฐํŽ˜์ด์Šค๋‹ค. ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ์ด๋ ‡๊ฒŒ ์ •์˜๋ผ ์žˆ๋‹ค.

type Stringer interface {
    String() string
}

ํƒ€์ž…์— String() string๋งŒ ๋ถ™์ด๋ฉด fmt.Println์ด ์ž๋™์œผ๋กœ ๊ทธ๊ฑธ ์“ด๋‹ค. 2๋ฒˆ์—์„œ Score์— String()์„ ๋ถ™์˜€์„ ๋•Œ ์ถœ๋ ฅ์ด 95์ ์œผ๋กœ ๋ฐ”๋€ ๊ฒŒ ๋ฐ”๋กœ ์ด ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋งŒ์กฑํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

io.Reader์™€ io.Writer

Go์—์„œ ๊ฐ€์žฅ ๋„๋ฆฌ ์“ฐ์ด๋Š” ๋‘ ์ธํ„ฐํŽ˜์ด์Šค๋‹ค. ๊ฐ๊ฐ ๋ฉ”์„œ๋“œ๊ฐ€ ๋”ฑ ํ•˜๋‚˜๋ฟ์ด๋‹ค.

type Reader interface {
    Read(p []byte) (n int, err error)
}
 
type Writer interface {
    Write(p []byte) (n int, err error)
}

Reader๋Š” โ€œ์–ด๋”˜๊ฐ€์—์„œ ๋ฐ”์ดํŠธ๋ฅผ ์ฝ์–ด์˜ฌ ์ˆ˜ ์žˆ๋‹คโ€, Writer๋Š” โ€œ์–ด๋”˜๊ฐ€๋กœ ๋ฐ”์ดํŠธ๋ฅผ ์“ธ ์ˆ˜ ์žˆ๋‹คโ€๋Š” contract๋‹ค. ํŒŒ์ผ, ๋„คํŠธ์›Œํฌ ์—ฐ๊ฒฐ, ๋ฉ”๋ชจ๋ฆฌ ๋ฒ„ํผ, ์••์ถ• ์ŠคํŠธ๋ฆผ์ด ์ „๋ถ€ ์ด ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋งŒ์กฑํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ๋ฐ์ดํ„ฐ์˜ ์ถœ์ฒ˜๊ฐ€ ๋ฌด์—‡์ด๋“  ๊ฐ™์€ ์ฝ”๋“œ๋กœ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๋‹ค.

// process๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ์–ด๋””์„œ ์˜ค๋Š”์ง€ ๋ชจ๋ฅธ๋‹ค. io.Reader๋ฉด ๋‹ค ๋ฐ›๋Š”๋‹ค
func process(r io.Reader) error {
    buf := make([]byte, 1024)
    for {
        n, err := r.Read(buf)
        if n > 0 {
            // buf[:n] ์ฒ˜๋ฆฌ
        }
        if err == io.EOF {
            return nil
        }
        if err != nil {
            return err
        }
    }
}
 
func main() {
    // ํŒŒ์ผ์„ ์—ด์–ด์„œ ๊ทธ๋Œ€๋กœ ๋„˜๊ธด๋‹ค. os.File์ด io.Reader๋ฅผ ๋งŒ์กฑํ•œ๋‹ค
    f, _ := os.Open("data.txt")
    defer f.Close()
    process(f)
 
    // ๋ฌธ์ž์—ด๋„ strings.NewReader๋กœ io.Reader๊ฐ€ ๋œ๋‹ค
    process(strings.NewReader("hello"))
}

process๋Š” ํŒŒ์ผ์ธ์ง€ ๋ฌธ์ž์—ด์ธ์ง€ ์‹ ๊ฒฝ ์“ฐ์ง€ ์•Š๋Š”๋‹ค. io.Reader๋ผ๋Š” contract๋งŒ ๋ณด๊ณ  ์ผํ•œ๋‹ค. ์ด๊ฒŒ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ์–ป๋Š” ์œ ์—ฐํ•จ์˜ ์‹ค์ „ ๋ชจ์Šต์ด๋‹ค.

์ธํ„ฐํŽ˜์ด์Šค ์ž„๋ฒ ๋”ฉ โ€” ์ž‘์€ ๊ฒƒ์„ ํ•ฉ์ณ ํฐ ๊ฒƒ์„

์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋‹ค๋ฅธ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ž„๋ฒ ๋”ฉํ•ด์„œ ์กฐํ•ฉํ•  ์ˆ˜ ์žˆ๋‹ค. ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ io.ReadCloser๊ฐ€ ๋Œ€ํ‘œ์ ์ด๋‹ค.

type Reader interface {
    Read(p []byte) (n int, err error)
}
 
type Closer interface {
    Close() error
}
 
// Reader์™€ Closer๋ฅผ ํ•ฉ์นœ ๊ฒƒ
type ReadCloser interface {
    Reader
    Closer
}

ReadCloser๋Š” Read์™€ Close๋ฅผ ๋‘˜ ๋‹ค ๊ฐ€์ง„ ๋ฌด์–ธ๊ฐ€๋ฅผ ๋œปํ•œ๋‹ค. ์ž‘์€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ ˆ๊ณ  ๋ธ”๋ก์ฒ˜๋Ÿผ ํ•ฉ์ณ ๋” ํฐ ๊ณ„์•ฝ์„ ๋งŒ๋“ ๋‹ค. ํฐ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ฒ˜์Œ๋ถ€ํ„ฐ ํ†ต์œผ๋กœ ์ •์˜ํ•˜๋Š” ๋Œ€์‹ , ํ•„์š”ํ•œ ์ž‘์€ ์กฐ๊ฐ๋“ค์„ ์กฐ๋ฆฝํ•˜๋Š” ์‹์ด๋‹ค.

์ž‘์€ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์ข‹์€ ์ธํ„ฐํŽ˜์ด์Šค

Go์—์„œ๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ์ ์€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์„ ํ˜ธํ•œ๋‹ค. io.Reader์ฒ˜๋Ÿผ ๋ฉ”์„œ๋“œ ํ•˜๋‚˜์งœ๋ฆฌ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ๊ฐ€์žฅ ์žฌ์‚ฌ์šฉํ•˜๊ธฐ ์ข‹๋‹ค. ๋งŒ์กฑ์‹œํ‚ค๊ธฐ ์‰ฝ๊ณ , ์กฐํ•ฉํ•˜๊ธฐ๋„ ์‰ฝ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. โ€œ์ด ์ธํ„ฐํŽ˜์ด์Šค์— ๋ฉ”์„œ๋“œ๋ฅผ ๋” ๋„ฃ์–ด์•ผ ํ•˜๋‚˜?โ€ ์‹ถ์œผ๋ฉด, ๋Œ€๊ฐœ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ชผ๊ฐœ๋Š” ๊ฒŒ ๋‚ซ๋‹ค.


6. โ€œ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ฐ›๊ณ  ๊ตฌ์กฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ผโ€

Go ์ฝ”๋“œ๋ฅผ ์ฝ๋‹ค ๋ณด๋ฉด ์ž์ฃผ ๋ณด์ด๋Š” ๊ด€์šฉ๊ตฌ๊ฐ€ ์žˆ๋‹ค. accept interfaces, return structs โ€” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ฐ›๊ณ  ๊ตฌ์กฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ผ.

๋œป์€ ๋‹จ์ˆœํ•˜๋‹ค.

  • ์ž…๋ ฅ(ํŒŒ๋ผ๋ฏธํ„ฐ)์€ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๋ฐ›์•„์„œ ์œ ์—ฐํ•˜๊ฒŒ โ€” ํ˜ธ์ถœ์ž๊ฐ€ ์–ด๋–ค ๊ตฌ์ฒด ํƒ€์ž…์„ ๋„˜๊ธฐ๋“  ๋ฉ”์„œ๋“œ๋งŒ ๋งž์œผ๋ฉด ๋ฐ›๋Š”๋‹ค.
  • ์ถœ๋ ฅ(๋ฐ˜ํ™˜๊ฐ’)์€ ๊ตฌ์ฒด ํƒ€์ž…(๊ตฌ์กฐ์ฒด)์œผ๋กœ ๋Œ๋ ค์ค˜์„œ ๋ช…ํ™•ํ•˜๊ฒŒ โ€” ๋ฐ›๋Š” ์ชฝ์ด ์ •ํ™•ํžˆ ๋ฌด์—‡์„ ๋ฐ›์•˜๋Š”์ง€ ์•ˆ๋‹ค.
// ์ž…๋ ฅ์€ io.Reader ์ธํ„ฐํŽ˜์ด์Šค โ€” ํŒŒ์ผ์ด๋“  ๋ฌธ์ž์—ด์ด๋“  ๋‹ค ๋ฐ›์Œ
// ์ถœ๋ ฅ์€ *bytes.Buffer ๊ตฌ์ฒด ํƒ€์ž… โ€” ๋ฐ›๋Š” ์ชฝ์ด ์ •ํ™•ํžˆ ๋ญ˜ ๋ฐ›๋Š”์ง€ ์•ˆ๋‹ค
func ReadAll(r io.Reader) *bytes.Buffer {
    var buf bytes.Buffer
    io.Copy(&buf, r)
    return &buf
}

์™œ ๋ฐ˜ํ™˜์€ ๊ตฌ์ฒด ํƒ€์ž…์ธ๊ฐ€

๋‘ ๊ฐ€์ง€ ์ด์œ ๊ฐ€ ์žˆ๋Š”๋ฐ, ๋” ์ง์ ‘์ ์ธ ๊ฑด ์ •๋ณด ๋ณด์กด์ด๋‹ค.

์ฒซ์งธ, ์ •๋ณด๊ฐ€ ๋ณด์กด๋œ๋‹ค. ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด ๋ฐ›๋Š” ์ชฝ์€ ๊ทธ ์ธํ„ฐํŽ˜์ด์Šค์— ์„ ์–ธ๋œ ๋ฉ”์„œ๋“œ๋งŒ ์“ธ ์ˆ˜ ์žˆ๋‹ค. ๊ตฌ์ฒด ํƒ€์ž…์„ ๋ฐ˜ํ™˜ํ•˜๋ฉด ๊ทธ ํƒ€์ž…์˜ ๋ชจ๋“  ๋ฉ”์„œ๋“œ์™€ ํ•„๋“œ๋ฅผ ๋‹ค ์“ธ ์ˆ˜ ์žˆ๋‹ค. ํ•ต์‹ฌ์€ ์ด ๋ฐฉํ–ฅ์ด ํ•œ์ชฝ์œผ๋กœ๋งŒ ์—ด๋ ค ์žˆ๋‹ค๋Š” ์ ์ด๋‹ค. ๊ตฌ์ฒด ํƒ€์ž…์„ ๋ฐ›์€ ํ˜ธ์ถœ์ž๋Š” ํ•„์š”ํ•˜๋ฉด ์ž๊ธฐ๊ฐ€ ์•Œ์•„์„œ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ์ขํž ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๋ฐ›์•„ ์ด๋ฏธ ์žƒ์–ด๋ฒ„๋ฆฐ ์ •๋ณด๋Š” ํ˜ธ์ถœ์ž๊ฐ€ ๋˜์‚ด๋ฆด ์ˆ˜ ์—†๋‹ค. ๊ทธ๋Ÿฌ๋‹ˆ ๋„“๊ฒŒ(๊ตฌ์ฒด ํƒ€์ž…์œผ๋กœ) ์ฃผ๊ณ , ์ขํžˆ๋Š” ๊ฑด ๋ฐ›๋Š” ์ชฝ์— ๋งก๊ธฐ๋Š” ๊ฒŒ ๋‚ซ๋‹ค.

๋‘˜์งธ, ๋ฐ˜ํ™˜๊ฐ’์„ ๋‚˜์ค‘์— ๋น„ํŒŒ๊ดด์ ์œผ๋กœ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๊ฑด ๋ฒ„์ €๋‹๊ณผ ์–ฝํžŒ ์ด์•ผ๊ธฐ์ธ๋ฐ, ์ •ํ™•ํžˆ ์งš์„ ํ•„์š”๊ฐ€ ์žˆ๋‹ค. โ€œ์ธํ„ฐํŽ˜์ด์Šค์— ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ๊ตฌํ˜„์ฒด๊ฐ€ ๋‹ค ๊นจ์ง„๋‹คโ€๋Š” ์‚ฌ์‹ค ์ž์ฒด๋Š” ๋ฐ˜ํ™˜ ์ „์šฉ ๋ฌธ์ œ๊ฐ€ ์•„๋‹ˆ๋ผ ์ธํ„ฐํŽ˜์ด์Šค ์ผ๋ฐ˜์˜ ์„ฑ์งˆ์ด๋‹ค. ์˜คํžˆ๋ ค ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์„ ๋•Œ ํ˜ธ์ถœ์ž๊ฐ€ ๊ตฌํ˜„์„ ๊ฐ•์ œ๋‹นํ•˜๋ฏ€๋กœ ๋” ์ง์ ‘์ ์ด๋‹ค. ๋ฐ˜ํ™˜์— ํŠนํ™”๋œ ์ง„์งœ ํฌ์ธํŠธ๋Š” ๋”ฐ๋กœ ์žˆ๋‹ค. ๋‚ด๊ฐ€ ๋ฐ˜ํ™˜ํ•œ ๊ฐ’์˜ ๊ธฐ๋Šฅ์„ ์•ž์œผ๋กœ ๋Š˜๋ฆด ์ž์œ ๊ฐ€ ์žˆ๋А๋ƒ๋‹ค.

๊ตฌ์ฒด ํƒ€์ž…์„ ๋ฐ˜ํ™˜ํ•˜๋ฉด ๋ฉ”์„œ๋“œ๋ฅผ ๊ทธ๋ƒฅ ๋”ํ•˜๋ฉด ๋œ๋‹ค. ๋ง์…ˆ์ด๋ผ ๊ธฐ์กด ํ˜ธ์ถœ์ž๊ฐ€ ์•ˆ ๊นจ์ง„๋‹ค.

func New() *Storage { ... }
 
// v2: ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด๋„ ๊ธฐ์กด ํ˜ธ์ถœ์ž๋Š” ๊ทธ๋Œ€๋กœ ๋™์ž‘ํ•œ๋‹ค
func (s *Storage) Backup() error { ... }

๋ฐ˜๋Œ€๋กœ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด, ๋ฐ˜ํ™˜๊ฐ’์— ์ƒˆ ๊ธฐ๋Šฅ์„ ์ฃผ๋Š” ๊ธธ์ด ๋‘˜ ๋‹ค ๊นจ๋Š” ๋ณ€๊ฒฝ๋ฟ์ด๋‹ค.

type Storage interface {
    Get(key string) string
}
func New() Storage { ... }
 
// v2์—์„œ Backup ๊ธฐ๋Šฅ์„ ์ฃผ๊ณ  ์‹ถ๋‹ค๋ฉด?
//   ๋ฐฉ๋ฒ• 1: ์ธํ„ฐํŽ˜์ด์Šค์— Backup() ์ถ”๊ฐ€ โ†’ ์ด ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋ชจ๋“  ๊ตฌํ˜„์ฒด(๋‚ด ๊ฒƒ + ์™ธ๋ถ€ mock)๊ฐ€ ๊นจ์ง
//   ๋ฐฉ๋ฒ• 2: ๋ฐ˜ํ™˜ ํƒ€์ž… ์ž์ฒด๋ฅผ ๋ฐ”๊ฟˆ โ†’ ํ•จ์ˆ˜ ์‹œ๊ทธ๋‹ˆ์ฒ˜๊ฐ€ ๊นจ์ง
// ์–ด๋А ์ชฝ์ด๋“  ๊นจ๋Š” ๋ณ€๊ฒฝ์ด๋‹ค

์ฆ‰ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ˆœ๊ฐ„ ๋ฐ˜ํ™˜๊ฐ’์˜ API๋ฅผ ๋น„ํŒŒ๊ดด์ ์œผ๋กœ ํ‚ค์šธ ๊ธธ์ด ๋ง‰ํžŒ๋‹ค. ๊ตฌ์ฒด ํƒ€์ž…์„ ๋ฐ˜ํ™˜ํ•˜๋ฉด ๊ทธ ๊ธธ์ด ์—ด๋ ค ์žˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ถœ๋ ฅ์€ ๊ตฌ์ฒด ํƒ€์ž…์œผ๋กœ ๋‘๋Š” ๊ฒŒ ์•ˆ์ „ํ•˜๋‹ค.

์ •๋ฆฌํ•˜๋ฉด

  • ์ •๋ณด ๋ณด์กด(์ฃผ ๊ทผ๊ฑฐ) โ€” ๊ตฌ์ฒด ํƒ€์ž…์„ ๋ฐ›์œผ๋ฉด ํ˜ธ์ถœ์ž๊ฐ€ ํ•„์š”ํ•  ๋•Œ ์ง์ ‘ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ์ขํž ์ˆ˜ ์žˆ๋‹ค. ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๋ฐ›์œผ๋ฉด ์žƒ์€ ์ •๋ณด๋ฅผ ๋˜์‚ด๋ฆด ์ˆ˜ ์—†๋‹ค.
  • ํ™•์žฅ ์ž์œ (๋ฐ˜ํ™˜ ํŠนํ™”) โ€” ๊ตฌ์ฒด ํƒ€์ž…์€ ๋ฉ”์„œ๋“œ๋ฅผ ๋”ํ•ด๋„ ์•ˆ ๊นจ์ง€์ง€๋งŒ, ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์†๋Œ€๋Š” ์ˆœ๊ฐ„ ๊ตฌํ˜„์ฒด๊ฐ€ ๊นจ์ง„๋‹ค.
  • โ€œ๋ฉ”์„œ๋“œ ์ถ”๊ฐ€๊ฐ€ ๊ตฌํ˜„์ฒด๋ฅผ ๊นฌ๋‹คโ€๋Š” ๊ฒƒ ์ž์ฒด๋Š” ์ธํ„ฐํŽ˜์ด์Šค ์ผ๋ฐ˜์˜ ์ฃผ์˜์ ์ด์ง€, ๋ฐ˜ํ™˜๋งŒ์˜ ๋ฌธ์ œ๋Š” ์•„๋‹ˆ๋‹ค.

์˜ˆ์™ธ: ์˜ค๋ฅ˜(error)

์ด ๊ทœ์น™์—๋Š” ์ž˜ ์•Œ๋ ค์ง„ ์˜ˆ์™ธ๊ฐ€ ํ•˜๋‚˜ ์žˆ๋‹ค. error๋Š” ์ธํ„ฐํŽ˜์ด์Šค์ธ๋ฐ๋„ ๋ฐ˜ํ™˜๊ฐ’์œผ๋กœ ์“ด๋‹ค. Go์—์„œ ํ•จ์ˆ˜๊ฐ€ ์˜ค๋ฅ˜๋ฅผ ๋Œ๋ ค์ค„ ๋•Œ๋Š” ๊ฑฐ์˜ ํ•ญ์ƒ error ์ธํ„ฐํŽ˜์ด์Šค ํƒ€์ž…์œผ๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์ด๊ฑด Go์˜ ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ ๊ด€๋ก€๊ฐ€ ์›Œ๋‚™ ํ™•๊ณ ํ•ด์„œ ์ƒ๊ธด ์˜๋„์  ์˜ˆ์™ธ๋‹ค. ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ๋Š” 08ํŽธ์—์„œ ๋”ฐ๋กœ ๋‹ค๋ฃฌ๋‹ค.


7. ๋นˆ ์ธํ„ฐํŽ˜์ด์Šค(any)์™€ ํƒ€์ž… ๋‹จ์–ธยทํƒ€์ž… ์Šค์œ„์น˜

๋งˆ์ง€๋ง‰์œผ๋กœ ํŠน์ˆ˜ํ•œ ์ธํ„ฐํŽ˜์ด์Šค ํ•˜๋‚˜๋ฅผ ๋ณด์ž. ๋ฉ”์„œ๋“œ๊ฐ€ 0๊ฐœ์ธ ์ธํ„ฐํŽ˜์ด์Šค๋‹ค.

interface{}   // ๋ฉ”์„œ๋“œ๊ฐ€ ํ•˜๋‚˜๋„ ์—†๋Š” ์ธํ„ฐํŽ˜์ด์Šค
any           // Go 1.18๋ถ€ํ„ฐ ์ถ”๊ฐ€๋œ ๋ณ„์นญ. interface{}์™€ ์™„์ „ํžˆ ๊ฐ™๋‹ค

๋ฉ”์„œ๋“œ๋ฅผ 0๊ฐœ ์š”๊ตฌํ•œ๋‹ค๋Š” ๊ฑด, ๋ชจ๋“  ํƒ€์ž…์ด ์ด ๊ณ„์•ฝ์„ ๋งŒ์กฑํ•œ๋‹ค๋Š” ๋œป์ด๋‹ค. ์–ด๋–ค ํƒ€์ž…์ด๋“  โ€œ๋ฉ”์„œ๋“œ 0๊ฐœ ๊ฐ€์ง€๊ธฐโ€๋Š” ์ž๋™์œผ๋กœ ์ถฉ์กฑํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๊ทธ๋ž˜์„œ any์—๋Š” ์–ด๋–ค ๊ฐ’์ด๋“  ๋‹ด์„ ์ˆ˜ ์žˆ๋‹ค.

var x any
x = 42           // ok
x = "hello"      // ok
x = Person{}     // ok โ€” ๋ฌด์—‡์ด๋“  ๋“ค์–ด๊ฐ„๋‹ค

Python์˜ ๋™์  ํƒ€์ž…๊ณผ ๋น„์Šทํ•œ ์ž๋ฆฌ๋‹ค. Python ๋ณ€์ˆ˜๋Š” ์›๋ž˜ ๋ฌด์—‡์ด๋“  ๋‹ด์œผ๋ฏ€๋กœ any๊ฐ€ ๊ธฐ๋ณธ ์ƒํƒœ์ธ ์…ˆ์ด๋‹ค. Go๋Š” ์ •์  ํƒ€์ž… ์–ธ์–ด๋ผ ์ผ๋ถ€๋Ÿฌ any๋ฅผ ์จ์•ผ ๊ทธ ๋А์Šจํ•จ์„ ์–ป๋Š”๋‹ค. Python์—๋„ ๋˜‘๊ฐ™์ด โ€œํƒ€์ž… ๊ฒ€์‚ฌ๋ฅผ ๋„๋Š”โ€ typing.Any๊ฐ€ ์žˆ๊ณ , ๋‘˜ ๋‹ค โ€œ๊ผญ ํ•„์š”ํ•  ๋•Œ๋งŒ, ๋‚จ์šฉ ๊ธˆ์ง€โ€๋ผ๋Š” ์กฐ์–ธ์ด ๋”ฐ๋ผ๋ถ™๋Š”๋‹ค(Python typing ๋…ธํŠธ์˜ Any).

any๋Š” ์–ธ์ œ ์“ฐ๊ณ , ์™œ ๋‚จ์šฉํ•˜๋ฉด ์•ˆ ๋˜๋‚˜

any์˜ ์ •๋‹นํ•œ ์“ฐ์ž„์€ ์Šคํ‚ค๋งˆ๊ฐ€ ๋ฏธ๋ฆฌ ์ •ํ•ด์ง€์ง€ ์•Š์€ ์™ธ๋ถ€ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃฐ ๋•Œ๋‹ค. ๋Œ€ํ‘œ์ ์œผ๋กœ ๊ตฌ์กฐ๋ฅผ ๋ชจ๋ฅด๋Š” JSON์„ ๋ฐ›์„ ๋•Œ๋‹ค.

// ์–ด๋–ค ๋ชจ์–‘์ผ์ง€ ๋ชจ๋ฅด๋Š” JSON์„ ์ผ๋‹จ ๋ฐ›์•„๋‘๋Š” placeholder
var data map[string]any
json.Unmarshal(raw, &data)

:=๋กœ ์ž๋™์œผ๋กœ ์•ˆ ๋˜๋‚˜?

โ€œGo๋Š” :=๋กœ ํƒ€์ž…์„ ์•Œ์•„์„œ ๋‹ฌ์•„์ฃผ๋Š”๋ฐ ์™œ ๊ตณ์ด any๋ƒโ€๊ณ  ์ƒ๊ฐํ•˜๊ธฐ ์‰ฝ๋‹ค. ํ•˜์ง€๋งŒ :=์˜ ํƒ€์ž… ์ถ”๋ก ์€ ์ปดํŒŒ์ผ ํƒ€์ž„์— ์šฐ๋ณ€ ํ‘œํ˜„์‹์˜ ํƒ€์ž…์„ ๋ณด๊ณ  ๋ชป ๋ฐ•๋Š” ๊ฒƒ์ด๋ผ(02ํŽธ), ๋Ÿฐํƒ€์ž„์—์•ผ ์ •ํ•ด์ง€๋Š” ๊ฐ’์—๋Š” ์“ธ ์ˆ˜ ์—†๋‹ค. JSON์ด ๊ฐ์ฒด์ผ์ง€ ๋ฐฐ์—ด์ผ์ง€ ์ˆซ์ž์ผ์ง€๋Š” ๋ฐ”์ดํŠธ๋ฅผ ๊นŒ๋ด์•ผ ์•„๋Š” ๋Ÿฐํƒ€์ž„ ์‚ฌ์‹ค์ด๋ผ ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ๋ฏธ๋ฆฌ ์•Œ ์ˆ˜ ์—†๋‹ค. ๊ฒŒ๋‹ค๊ฐ€ json.Unmarshal์€ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š๊ณ  ๋ฐ›์„ ๋ณ€์ˆ˜์— ํฌ์ธํ„ฐ๋กœ ์จ๋„ฃ์œผ๋ฏ€๋กœ(Unmarshal(data, &v)), :=๊ฐ€ ์ถ”๋ก ํ•  ์šฐ๋ณ€ ํ‘œํ˜„์‹์กฐ์ฐจ ์—†๋‹ค. ๊ทธ๋ž˜์„œ ๋ฐ›์„ ๋ณ€์ˆ˜์— ์ •์ ์œผ๋กœ ์ค„ ์ˆ˜ ์žˆ๋Š” ํƒ€์ž…์€ โ€œ๋ฌด์—‡์ด๋“ โ€์„ ๋œปํ•˜๋Š” any๋ฟ์ด๋‹ค. ์„ค๋ น ํŒŒ์‹ฑ ํ•จ์ˆ˜๊ฐ€ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋”๋ผ๋„ ๋ชจ์–‘์„ ๋ชจ๋ฅด๋ฉด ๊ทธ ๋ฐ˜ํ™˜ ํƒ€์ž…์ด any๋ผ, v := decode(raw)์˜ v๋„ ๊ฒฐ๊ตญ any๋‹ค. :=๋Š” ์šฐ๋ณ€์ด ์ฃผ๋Š” ๊ฒƒ๋ณด๋‹ค ๋” ๊ตฌ์ฒด์ ์ธ ํƒ€์ž…์„ ๋งŒ๋“ค์–ด๋‚ด์ง€ ๋ชปํ•œ๋‹ค.

ํ•˜์ง€๋งŒ ๋‚จ์šฉ์€ ํ”ผํ•ด์•ผ ํ•œ๋‹ค. any์— ๊ฐ’์„ ๋‹ด๋Š” ์ˆœ๊ฐ„ ํƒ€์ž… ์ •๋ณด๊ฐ€ ์‚ฌ๋ผ์ ธ์„œ, ์ปดํŒŒ์ผ๋Ÿฌ์˜ ํƒ€์ž… ๊ฒ€์‚ฌ๋ผ๋Š” Go์˜ ๊ฐ€์žฅ ํฐ ์žฅ์ ์„ ์Šค์Šค๋กœ ๋ฒ„๋ฆฌ๋Š” ๊ผด์ด ๋œ๋‹ค. ํ•„๋“œ๊ฐ€ ์ •ํ•ด์ง„ ๋ฐ์ดํ„ฐ๋ผ๋ฉด 06ํŽธ์—์„œ ๊ถŒํ•œ ๋Œ€๋กœ ๊ตฌ์กฐ์ฒด๋ฅผ ์“ฐ๋Š” ๊ฒŒ ๊ฑฐ์˜ ํ•ญ์ƒ ๋‚ซ๋‹ค.

ํƒ€์ž… ๋‹จ์–ธ โ€” ๋‹ด๊ธด ๊ตฌ์ฒด ํƒ€์ž…์„ ๊บผ๋‚ด๊ธฐ

3๋ฒˆ์—์„œ โ€œ์ธํ„ฐํŽ˜์ด์Šค ๊ฐ’ ์•ˆ์—๋Š” ํ•ญ์ƒ ๊ตฌ์ฒด ํƒ€์ž…์ด ๋“ค์–ด์žˆ๋‹คโ€๊ณ  ํ–ˆ๋‹ค. ๊ทธ ๊ตฌ์ฒด ํƒ€์ž…์„ ๋‹ค์‹œ ๊บผ๋‚ด๋Š” ๊ฒŒ ํƒ€์ž… ๋‹จ์–ธ(type assertion)์ด๋‹ค.

var i any = 42
 
n := i.(int)      // "i ์•ˆ์— ๋“  ๊ฒŒ int์ด๋‹ค"๋ผ๊ณ  ๋‹จ์–ธํ•˜๊ณ  ๊บผ๋ƒ„
fmt.Println(n)    // 42

๋ฌธ์ œ๋Š” ๋‹จ์–ธ์ด ํ‹€๋ฆฌ๋ฉด ํŒจ๋‹‰์ด ๋‚œ๋‹ค๋Š” ์ ์ด๋‹ค. i์— ๋“  ๊ฒŒ int์ด ์•„๋‹Œ๋ฐ i.(int)์„ ํ•˜๋ฉด ํ”„๋กœ๊ทธ๋žจ์ด ์ฃฝ๋Š”๋‹ค. ๊ทธ๋ž˜์„œ comma-ok ํ˜•ํƒœ๋ฅผ ์“ฐ๋Š” ๊ฒŒ ์•ˆ์ „ํ•˜๋‹ค. ์„ฑ๊ณต ์—ฌ๋ถ€๋ฅผ ok๋กœ ๋ฐ›์•„ ํŒจ๋‹‰์„ ํ”ผํ•œ๋‹ค.

var i any = 42
 
n, ok := i.(string)   // i๋Š” int์ธ๋ฐ string์œผ๋กœ ๋‹จ์–ธ
if ok {
    fmt.Println("๋ฌธ์ž์—ด:", n)
} else {
    fmt.Println("๋ฌธ์ž์—ด์ด ์•„๋‹˜")  // ์ด์ชฝ์ด ์‹คํ–‰๋จ. ํŒจ๋‹‰ ์—†์Œ
}

Python์˜ isinstance๋กœ ๋จผ์ € ํ™•์ธํ•˜๊ณ  ์“ฐ๋Š” ํŒจํ„ด๊ณผ ๋ฐœ์ƒ์ด ๊ฐ™๋‹ค.

# Python
if isinstance(i, str):
    print("๋ฌธ์ž์—ด:", i)
else:
    print("๋ฌธ์ž์—ด์ด ์•„๋‹˜")

ํƒ€์ž… ์Šค์œ„์น˜ โ€” ์—ฌ๋Ÿฌ ํƒ€์ž…์„ ๋ถ„๊ธฐ

ํ™•์ธํ•  ํƒ€์ž…์ด ์—ฌ๋Ÿฌ ๊ฐœ๋ฉด if ๋‹จ์–ธ์„ ์ค„์ค„์ด ์“ฐ๋Š” ๋Œ€์‹  ํƒ€์ž… ์Šค์œ„์น˜(type switch)๋ฅผ ์“ด๋‹ค.

func describe(i any) string {
    switch v := i.(type) {
    case int:
        return fmt.Sprintf("์ •์ˆ˜ %d", v)
    case string:
        return fmt.Sprintf("๋ฌธ์ž์—ด %q", v)
    case Person:
        return fmt.Sprintf("Person %s", v.Name)
    default:
        return "์•Œ ์ˆ˜ ์—†๋Š” ํƒ€์ž…"
    }
}

i.(type)์€ ํƒ€์ž… ์Šค์œ„์น˜ ์•ˆ์—์„œ๋งŒ ์“ฐ๋Š” ํŠน์ˆ˜ ๋ฌธ๋ฒ•์ด๋‹ค. ๊ฐ case์—์„œ v๋Š” ๊ทธ ํƒ€์ž…์œผ๋กœ ํ™•์ •๋ผ, ๋ณ„๋„ ๋‹จ์–ธ ์—†์ด ๋ฐ”๋กœ ์“ธ ์ˆ˜ ์žˆ๋‹ค. Python์—์„œ isinstance๋ฅผ ์—ฐ๋‹ฌ์•„ ํ™•์ธํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ๊น”๋”ํ•˜๊ฒŒ ๋Œ€์ฒดํ•œ๋‹ค.

nil ํฌ์ธํ„ฐ์—๋„ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค

Python์—์„œ๋Š” None.foo()๊ฐ€ ์ฆ‰์‹œ ์—๋Ÿฌ์ง€๋งŒ, Go์—์„œ๋Š” nil ํฌ์ธํ„ฐ ๋ฆฌ์‹œ๋ฒ„๋กœ๋„ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ฉ”์„œ๋“œ ์•ˆ์—์„œ ๋ฆฌ์‹œ๋ฒ„๊ฐ€ nil์ธ์ง€ ์ง์ ‘ ๊ฒ€์‚ฌํ•ด ์ฒ˜๋ฆฌํ•˜๋„๋ก ์งค ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค(06ํŽธ์—์„œ ๋ณธ โ€œnil ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜๋ฉด ํฌ์ธํ„ฐ ๋ฆฌ์‹œ๋ฒ„โ€ ๊ทœ์น™๊ณผ ์ด์–ด์ง„๋‹ค). ๋‹จ, ๋ฉ”์„œ๋“œ ์•ˆ์—์„œ ๊ทธ nil ๋ฆฌ์‹œ๋ฒ„๋ฅผ ์—ญ์ฐธ์กฐํ•˜๋ฉด ๊ทธ๋•Œ๋Š” ํŒจ๋‹‰์ด ๋‚œ๋‹ค.