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++๋ก ๋น์
์ด ๊ตฌ๋๋ ๋ค๋ฅธ ์ธ์ด์๋ ๋๊ฐ์ด ์๋ค.
| ๊ตฌ์ฒด ํ์ (์ธ์คํด์คํ ๊ฐ๋ฅ) | ์ถ์ ํ์ (์ธ์คํด์คํ ๋ถ๊ฐ) | |
|---|---|---|
| Python | list, dict, ์ฌ์ฉ์ class | abc.ABC, typing.Protocol, collections.abc.Sequence |
| C++ | ๊ตฌ์ฒด ํด๋์ค | ์์ ๊ฐ์ํจ์๋ฅผ ๊ฐ์ง ์ถ์ ํด๋์ค |
| Go | int, ๊ตฌ์กฐ์ฒด, ์ฌ๋ผ์ด์ค, ๋งต, ํฌ์ธํฐ | ์ธํฐํ์ด์ค |
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๋ฆฌ์๋ฒ๋ฅผ ์ญ์ฐธ์กฐํ๋ฉด ๊ทธ๋๋ ํจ๋์ด ๋๋ค.