GoLang ๋ฌธ๋ฒ• ์‹œ์ž‘ํ•˜๊ธฐ

๋ณ€์ˆ˜


GoLang์˜ ๋ณ€์ˆ˜๋Š” ํฌ๊ฒŒ 2๊ฐ€์ง€ const(์ƒ์ˆ˜), var(๋ณ€์ˆ˜)๋กœ ์ด๋ฃจ์–ด์ง„๋‹ค.

  • const
    • const name string = โ€œSanbalโ€
  • var
    • var name string = โ€œSanbalโ€
    • name := โ€œStringโ€
      • ์œ„์™€ ๊ฐ™์ด ์ž‘์„ฑํ•˜๋ฉด, Go๊ฐ€ ํƒ€์ž…์ถ”๋ก ์„ ํ†ตํ•ด์„œ ํƒ€์ž…์ด ์ง€์ •๋œ๋‹ค.
      • := ์„ ์“ธ๋•Œ ํƒ€์ž…์ด ์ง€์ •๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋‚˜์ค‘์— ๋‹ค๋ฅธ type์„ ๋„ฃ์„ ์ˆ˜ ์—†๋‹ค.

Function


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// ๊ธฐ๋ณธ์ ์ธ function์˜ ํ˜•ํƒœ
func len(name string) int {
	return len(name)
}

// ์ž…๋ ฅ์„ ์—ฌ๋Ÿฌ๊ฐœ ๋ฐ›๋Š” ๊ฒฝ์šฐ
func words(words ...string) {
	// ์ž…๋ ฅ๋ฐ›์€ ๊ฐ’์„ list ํ˜•ํƒœ๋กœ ๋‚˜ํƒ€๋‚ธ๋‹ค.
	fmt.Println(words)
}

// ๋ฐ˜ํ™˜์„ ์—ฌ๋Ÿฌ๊ฐœํ•˜๋Š” ๊ฒฝ์šฐ, python์ฒ˜๋Ÿผ ๊ฐ€๋Šฅํ•˜๋‹ค.
func lenAndUpper(name string) (int, string) {
	return len(name), strings.ToUpper(name)
}
// -> namelen, up := lenAndUpper('sanbal')

// naked func
// ๋ฏธ๋ฆฌ ๋ฐ˜ํ™˜ํ•  ๋ณ€์ˆ˜๋ฅผ ์ง€์ •ํ•ด return๋  ๋•Œ ํ•ด๋‹น ๋ณ€์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
func naked(name string) (lenght int, uppercase string) {
	// ์œ„์—์„œ ์ด๋ฏธ ๋ณ€์ˆ˜๊ฐ€ ํ• ๋‹น๋ฌ์œผ๋‹ˆ๊นŒ :=์™€ ๊ฐ™์€ ์‹์€ ์“ฐ์ง€ ์•Š๋„๋ก ํ•˜์ž!
	lenght = len(name)
	uppercase = strings.ToUpper(name)
	return
	// return lenght, uppercase ํ•ด๋„ ์ƒ๊ด€์€ ์—†์Œ!
}

defer

ํ•จ์ˆ˜๊ฐ€ ์ข…๋ฃŒ๋˜๋ฉด ์‹คํ–‰๋˜๋Š” ๋ช…๋ น์–ด

  • return์ด ๋ฐœ์ƒํ•˜๊ณ  ๋‚œ ๋’ค์— ์‹คํ–‰๋œ๋‹ค.
  • ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์—์„œ ๊ฝค ์œ ์šฉํ•˜๊ฒŒ ์“ฐ์ผ ๋“ฏํ•˜๋‹ค!
1
2
3
4
5
6
7
func naked(name string) (lenght int, uppercase string) {
	defer fmt.Println("I'm done!")

	lenght = len(name)
	uppercase = strings.ToUpper(name)
	return
}

๋ฐ˜๋ณต๋ฌธ For


Go์—์„œ ๋ฐ˜๋ณต๋ฌธ์€ for ํ•˜๋‚˜๋ฟ์ด๋‹ค. map, forEach์™€ ๊ฐ™์€ ๊ธฐ๋Šฅ์€ ์—†๊ณ  ๋”ฑ for๋งŒ~~(์‹ฌํ”Œํ•ด์„œ ์˜คํžˆ๋ ค ์„น์‹œํ•ด)~~ for๋ฌธ์„ ์œ„ํ•ด์„œ range๊ฐ€ ์žˆ๋Š”๋ฐ python์—์„œ enumerate() ๊ฐ™์€ ๋Š๋‚Œ์œผ๋กœ ์ž‘๋™ํ•œ๋‹ค.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
func superAdd(numbers ...int) int {
	total := 0
	// range๋ฅผ ์ด์šฉํ•œ ๋ฐฉ๋ฒ•
	for i, number := range numbers {
		total += number
	}

	// ์œ„์™€๊ฐ™์ด ์“ฐ๋ฉด i์— ๋นจ๊ฐ„์ค„์ด ์ƒ๊ธฐ๋Š”๋ฐ, ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๋ณ€์ˆ˜๊ฐ€ ์žˆ์œผ๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋‚œ๋‹ค;;;;;
	// ๊ทธ๋ž˜์„œ _๋ฅผ ์ด์šฉํ•ด์„œ ๋ฌด์‹œํ•ด๋ฒ„๋ฆด ์ˆ˜ ์žˆ์Œ! (python์—์„œ๋Š” _๋ฅผ ๋ณ€์ˆ˜๋กœ ์“ฐ๋Š” ๋ช…์‹œ์ ์ธ ๋Š๋‚Œ์ด์˜€๋Š”๋ฐ, ์–˜๋Š” ์ง„์งœ๋กœ ๋ชป์“ด๋‹ค;;;)
	for _, number := range numbers {
		total += number
	}
	
	// ๋ฌผ๋ก  ์ „ํ†ต์ ์ธ ๋ฐฉ์‹๋„ ์ง€์›ํ•œ๋‹ค.
	for i := 0; i< len(numbers); i++ {
		fmt.Println(i, numbers[i])
	}

	return total
}

์กฐ๊ฑด๋ฌธ if else


if else

if else๋Š” ๋ญ…์‹ฌํ”Œํ•˜๋‹ค

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
func canIDrink(age int) bool {
	/*
	if age < 18 {
		return false
	} else {
		return true
	}
	*/

	// ๊ทผ๋ฐ ์œ„์™€๊ฐ™์ด ์“ฐ๋Š” ๊ฒƒ๋ณด๋‹จ ์ด๊ฒŒ ๋” ์ฟจ, ํŽ€, ์„น์‹œํ•˜๊ธฐ๋„ ํ•˜๊ณ  vscode์—์„œ extension์œผ๋กœ ์ถ”์ฒœํ•ด์ค€๋‹ค.
	if age < 18 {
		return false
	} 
	return true
}

Switch

python์—” ์—†๊ณ , C์—์„œ ์จ๋ณธ ์ดํ›„๋กœ ์ •๋ง ์˜ค๋žœ๋งŒ์ธ๋ฐ ๊ฐ€๋” ํ•„์š”ํ•œ ์ผ์ด ์ƒ๊ธด๋‹ค.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
func canIDrink(age int) bool {
	// ์กฐ๊ฑด์ด ๊ฑธ๋ฆฌ๋Š” ๋ณ€์ˆ˜๋ฅผ ์ง€์ •ํ•˜๊ฑฐ๋‚˜
	switch age {
	case 10:
		return false
	case 18:
		return true
	}

	// ์กฐ๊ฑด์„ ๋ช…์‹œํ•˜๊ฑฐ๋‚˜
	switch {
	case age < 18:
		return false
	case age == 18:
		return true
	case age > 50:
		return false
	}

	return false
}

variable extension

go์—๋งŒ ์žˆ๋Š” ๊ธฐ๋Šฅ์ธ๋ฐ, ์กฐ๊ฑด๋ฌธ ์•ˆ์—์„œ ์‚ฌ์šฉํ•  ๋ณ€์ˆ˜๋ฅผ ์กฐ๊ฑด๋ฌธ ์•ž์—์„œ ์‚ฌ์šฉํ•˜๋Š”…? ๊ทธ๋Ÿฐ ๋ฌธ๋ฒ•์ด๋‹ค.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// if else
if koreanAge := age + 2; koreanAge< 18 {
	return false
}
return true

// switch
switch koreanAge := age + 2; koreanAge {
case 10:
	return false
case 18:
	return true
}

Pointer


C์–ธ์–ด ์ดํ›„๋กœ ์ •๋ง ์˜ค๋žœ๋งŒ์— ๋ณด๋Š” ๊ธฐ๋Šฅ์ด๋‹ค! C ๋ฐฐ์šธ๋•Œ ์—ฌ๊ธฐ์„œ ๋งŽ์ด๋“ค ํฌ๊ธฐํ–ˆ์—ˆ์ง€… ๊ธฐ๋ณธ์  ๊ฐœ๋…์€ ๊ฐ™๊ณ , ์‚ฌ์šฉ๋ฒ•๋„ ๋น„์Šทํ•˜๋‹ค.

  • & : address(์ฃผ์†Œ)
  • * : address์˜ ๊ฐ’
  • := ์ด ์•„๋‹ˆ๋ผ ์„ ์–ธ๋งŒ ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, var potiner *int๋ฅผ ์‚ฌ์šฉํ•˜์ž
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
func main() {
	a := 2
	b := &a
	fmt.Println(b, *b)
	// -> 0x1400001c070 2

	a = 10
	fmt.Println(b, *b)
	// -> 0x1400001c070 10

	*b = 20
	fmt.Println(a)
	// 20
}

Array & Slice


๋ฐฐ์—ด์—๋Š” 2๊ฐ€์ง€ ์ข…๋ฅ˜๊ฐ€ ์žˆ๋‹ค! ๋ผ๊ณ  ํ•˜๊ธฐ์—” ์กฐ๊ธˆ ์• ๋งคํ•˜๊ธดํ•œ๋ฐ, lenght๋ฅผ ์ง€์ •ํ•ด์ฃผ๊ฑฐ๋‚˜ ์•ˆํ•ด์ฃผ๊ฑฐ๋‚˜๋กœ 2๊ฐ€์ง€๋กœ ๋‚˜๋‰œ๋‹ค. array๋Š” lenght๊ฐ€ ๊ณ ์ •๋˜๊ณ , slice๋Š” ๊ณ ์ •๋˜์ง€ ์•Š๋Š”๋‹ค.

1
2
3
4
5
6
7
// array
func main() {
	names := [5]string {"sanbal", "hello", "world"}
	fmt.Println(names)
	names[3] = "hi"
	fmt.Println(names)
}
1
2
3
4
5
6
7
// slice
func main() {
	names := []string {"sanbal", "hello", "world"}
	fmt.Println(names)
	names = append(names, "hi", "happy")
	fmt.Println(names)
}
  • array๋Š” ์ „ํ†ต์ ์ธ ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉ! ๋‹น์—ฐํžˆ lenght๋ฅผ ๋ฒ—์–ด๋‚˜๋Š” index์—๋Š” ๊ฐ’์„ ๋„ฃ์„ ์ˆ˜ ์—†๋‹ค. vscode๊ฐ€ ์•Œ๋ ค์ฃผ๋˜๋ฐ?
  • slice๋Š” python์—์„œ ์‚ฌ์šฉํ•˜๋“ฏ์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ. append๋Š” ์žฌํ• ๋‹นํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค. ์†”์งํžˆ python ์–ด๋–ค๊ฑฐ๋Š” ํ•จ์ˆ˜๋Š” ์ž๊ธฐ์ž์‹  ๋ฐ”๊พธ๊ณ , ์–ด๋–ค๊ฑฐ๋Š” ํ• ๋‹นํ•ด์•ผํ•˜๊ณ  ๊ทธ๋ž˜์„œ ์กฐ๊ธˆ ํ—ท๊ฐˆ๋ ธ์—ˆ๋‹ค…

Map


map๋„ ์‹ฌํ”Œํ•˜๋‹ค. ์‹ฌํ”Œํ•˜๋‹ค ๋ชปํ•ด ๊ธฐ๋Šฅ์ด ์—†๋‹ค. ์—†์œผ๋ฉด ๋งŒ๋“ค์–ด ์จ์•ผ์ง€ ๋ญ…

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
func main() {
	// key์™€ value์˜ ์ž๋ฃŒํ˜•์€ ๋”ฑ ์ •ํ•ด์„œ!
	ksanbal := map[string]string {
		"name": "ksanbal",
		"age": "SuperSecret",
	}
	fmt.Println(ksanbal)

	// ์ถ”๊ฐ€๋Š” ์ด๋ ‡๊ฒŒ
	ksanbal["blog"] = "devksanbal.site"
	fmt.Println(ksanbal)

	// for range๊ฐ€ ๊ฐ€๋Šฅ!!
	for key, value := range ksanbal {
		fmt.Println(key, value)
	}
}

๋น„์–ด์žˆ๋Š” map์„ ๋งŒ๋“ค๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ?

1
2
3
4
5
6
7
8
// ์ž˜๋ชป๋œ ๋ฐฉ๋ฒ•
var result map[string]string 
result['hello'] = 'world' // ๊ทธ๋Ÿด ๋“ฏ ํ•ด๋ณด์ด์ง€๋งŒ, panic์„ ๋ฐœ์ƒํ•œ๋‹ค. result๊ฐ€ nil๋กœ ์ฒ˜๋ฆฌ๋˜๊ฒŒ ๋–„๋ฌธ

// ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉ๋ฒ•
result := map[string]string{} // ๋์— {}๋กœ ์ดˆ๊ธฐํ™”ํ•ด์ค€๋‹ค.
var result = make(map[string]string) // make() ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด ์ดˆ๊ธฐํ™”ํ•œ๋‹ค.
result['hello'] = 'world'

Struct


map ํ˜•ํƒœ์— value๋ฅผ ๋‹ค์–‘ํ•œ ์ž๋ฃŒํ˜•์œผ๋กœ ํ•˜๊ณ ์‹ถ์„ ๋•Œ๊ฐ€ ์žˆ๋‹ค. ๋ณดํ†ต ๊ทธ๋ ‡๊ฒŒ ๊ด€๋ฆฌํ•˜๊ธฐ๋„ ํ•˜๊ณ . go์—๋Š” class๊ฐ€ ์—†๋Š” ๋Œ€์‹  struct๊ฐ€ ์žˆ๋‹ค.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
type persion struct {
	name string
	age int
	anything []string
}

func main() {
	ksanbal := persion{"ksanbal", 18, []string{"hello", "world"}}
	// ๋˜๋Š”
	ksanbal = person{
		name: "ksanbal",
		age: 18,
		anything: []string{"hello", "world"},
	}
	// keyword ๋ฐฉ์‹๊ณผ positioned ๋ฐฉ์‹์„ ์„ž์–ด ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.
}

class ๋Œ€์‹  struct๋ฅผ ์“ฐ๋‹ˆ๊นŒ ๊ทธ๋ฆฌ์šด ๋ถ€๋ถ„์ด ์ƒ๊ธฐ๋Š”๋ฐ ๋ฐ”๋กœ private์™€ construct์ด๋‹ค. go์—์„œ๋Š” ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„ํ• ๊นŒ ์ผ๋‹จ account๋ผ๋Š” ํด๋”๋ฅผ ๋งŒ๋“ค๊ณ , ๊ทธ ์•ˆ์— account.go ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜์ž.

Go์—์„œ๋Š” ์žฌ๋ฐŒ๊ฒŒ๋„ ๋ณ€์ˆ˜, struct, func์˜ ์ด๋ฆ„ ์•ž๊ธ€์ž๋ฅผ ์†Œ๋ฌธ์ž๋กœํ•˜๋ฉด private, ๋Œ€๋ฌธ์ž๋กœํ•˜๋ฉด public์ด๋‹ค. ์•„๋ž˜์™€ ๊ฐ™์ด account๋ฅผ ์ƒ์„ฑํ•˜๋ฉด, ์ค‘๊ฐ„์— account์— .์œผ๋กœ ์ ‘๊ทผํ•˜์—ฌ ๊ฐ’์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋‹ค.

Constructor

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
// account.go
package account

// Account struct
type Account struct {
	owner string
	balance int
}

// NewAccount creates Account
// instance๋ฅผ ๋งŒ๋“ค์–ด ๋ณต์ œํ•˜๋Š” ๊ฑด ๋ฉ”๋ชจ๋ฆฌ ๋‚ญ๋น„๋‹ˆ๊นŒ, pointer๋ฅผ ์ด์šฉํ•ด ๊ฐ’์„ ์ „๋‹ฌํ•˜์ž.
func NewAccount(owner string) *Account {
	account := Account{
		owner: owner,
		balance: 0,
	}
	return &account
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// main.go
package main

import (
	"fmt"

	"github.com/devKsanbal/account"
)

func main() {
	account := account.NewAccount("ksanbal")
	fmt.Println(account)
}

Method

์ด๋ฒˆ์—” struct์˜ method๋“ค์„ ์ƒ์„ฑํ•ด๋ณด์ž. ์—ฌ๊ธฐ์„œ Deposit method์—์„œ *์— ์œ ์˜ํ•˜์ž! go๋Š” ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ• ๋•Œ ๊ฐ’์„ ๋ณต์‚ฌํ•ด์„œ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์—, pointer๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ฉด ํ•จ์ˆ˜ ๋‚ด์—์„œ๋งŒ ๊ฐ’์ด ๋ณ€๊ฒฝ๋œ๋‹ค.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// GetBalance ํ˜„์žฌ ๊ธˆ์•ก ์ถœ๋ ฅ
func (a Account) GetBalance() int {
	return a.balance
}

// Deposit ์ž…๊ธˆ
func (a *Account) Deposit(amount int) {
	a.balance += amount
}

// String fmt.Println(account) ํ–ˆ์„๋•Œ ๋‚˜์˜ฌ String ํ•จ์ˆ˜ override
func(a Account) String() string {
	return fmt.Sprint(a.GetOwner(), "'s account\nHas : ", a.GetBalance())
}

Error ์ฒ˜๋ฆฌ


go์—์„œ๋Š” ์—๋Ÿฌ๊ฐ€ ๋œจ๋ฉด ํ”„๋กœ๊ทธ๋žจ์„ ๋ฉˆ์ถ”๊ณ  ๊ทธ ๋‚ด์šฉ์„ ๋ฑ‰์–ด์ฃผ์ง€ ์•Š๋Š”๋‹ค. ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ์ง์ ‘ ์—๋Ÿฌ๋ฅผ ๊ธฐ๋กํ•˜๊ณ  ๋ฐœ์ƒ์‹œ์ผœ์•ผํ•œ๋‹ค. log.Fatalln()์€ ์—๋Ÿฌ ๋‚ด์šฉ์„ ์ถœ๋ ฅํ•˜๊ณ  ํ”„๋กœ๊ทธ๋žจ์„ ์ข…๋ฃŒํ•ด์ค€๋‹ค.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
// account.go
func (a *Account) Withdraw(amount int) error {
	if a.balance < amount {
		var errNoMoney = errors.New("Can't withdraw, you are poor")
		return errNoMoney
	}
	a.balance -= amount
	return nil // ๋ญ๋“  return ํ•ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์—, nil(null,None)์œผ๋กœ ๋ฐ˜ํ™˜
}

// main.go
func main() {
	account := account.NewAccount("ksanbal")
	account.Deposit(10)
	err := account.Withdraw(20)
	if err != nil {
		log.Fatalln(err)
	}
	fmt.Println(account)
}

Dictionary


์ด๋ฒˆ์—” struct๊ฐ€ ์•„๋‹Œ dictinary์— method๋ฅผ ์ถ”๊ฐ€ํ•ด๋ณด์ž. ์ „์— map์— ๊ธฐ๋Šฅ์ด ์—†๋‹ค๋Š” ์–˜๊ธฐ๋ฅผ ํ–ˆ์—ˆ๋Š”๋ฐ ๊ทธ๊ฑธ ๋Œ€์‹  ํ•˜๋Š” ๋Š๋‚Œ์œผ๋กœ ๋งŒ๋“ค๋ฉด ๋  ๊ฒƒ ๊ฐ™๋‹ค.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// mydict.go
var (
	errNotFound = errors.New("Not Found")
	errCantUpdate = errors.New("Can't update non-existing word")
	errCantDelete = errors.New("Can't delete non-existing word")
	errAlreadyExist = errors.New("Already Exit")
)

// Dictionary type
type Dictionary map[string]string

// Search for word
func (d Dictionary) Search(word string) (string, error) {
	value, exists := d[word] // dictonary[value]๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ฐ’๊ณผ, ์กด์žฌ์—ฌ๋ถ€๋ฅผ ๋ฐ˜ํ™˜ํ•ด์ค€๋‹ค. ๊ทธ ์ ์„ ์ด์šฉํ•˜์ž
	if exists {
		return value, nil
	}
	return "", errNotFound
}

// Add Add a word
func (d Dictionary) Add(word, def string) error {
	_, err := d.Search(word)
	switch err {
	case errNotFound:
		d[word] = def
	case nil:
		return errAlreadyExist
	}
	return nil
}

// Update update a word
func (d Dictionary) Update(word, def string) error {
	_, err := d.Search(word)
	switch err {
	case nil:
		d[word] = def
	case errNotFound:
		return errCantUpdate
	}
	return nil
}

// Delete delete word
func (d Dictionary) Delete(word string) error{
	_, err := d.Search(word)
	switch err {
	case nil:
		delete(d, word)
	case errNotFound:
		return errCantDelete
	}
	return nil
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// main.go
func main() {
	// Search
	dictionary := mydict.Dictionary{"first": "First Word"}
	definition, err := dictionary.Search("second")
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(definition)
	}

	definition, err = dictionary.Search("first")
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(definition)
	}

	// Add
	dictionary = mydict.Dictionary{}
	err = dictionary.Add("hello", "Greeting")
	if err != nil {
		fmt.Println(err)
	}
	
	definition, _ = dictionary.Search("hello")
	fmt.Println(definition)

	err2 := dictionary.Add("hello", "Greeting")
	if err2 != nil {
		fmt.Println(err2)
	}

	// Update
	dictionary = mydict.Dictionary{}
	dictionary.Add("hello", "First")
	// err := dictionary.Update("hello", "Second")
	err = dictionary.Update("test", "Second")
	if err != nil {
		fmt.Println(err)
	} else {
		word, _ := dictionary.Search("hello")
		fmt.Println(word)
	}

	// Delete
	dictionary = mydict.Dictionary{}
	dictionary.Add("hello", "First")
	dictionary.Add("world", "Second")
	fmt.Println(dictionary)
	err = dictionary.Delete("hello")
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(dictionary)
	}
}

GoRoutines


go์—์„œ ๊ฐ€์žฅ ์„น์‹œํ•œ ์ ์€ ๋ฐ”๋กœ Goroutines๋ผ๋Š” ๋™์‹œ์‹คํ–‰์ด๋‹ค. ์‚ฌ์šฉ๋ฒ•๋„ ์‰ฝ๋‹ค.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
func main() {
	people := [4]string {"ksanbal", "hyunkyun", "hello", "world"}

	for _, person := range people {
		go isSexy(person)
	}
}

func isSexy(person string) {
	time.Sleep(time.Second * 5)
	fmt.PrintLn(person, " is sexy")
}

๊ทผ๋ฐ ๊ทธ๋ƒฅ ์ด๋ ‡๊ฒŒ ์“ฐ๋ฉด ์•„๋ฌด ๊ฒฐ๊ณผ๋„ ๋ชป๋ณด๊ณ  ๋๋‚œ๋‹ค. ์™œ์ผ๊นŒ? ๊ทธ ์ด์œ ๋Š” main()ํ•จ์ˆ˜๋Š” GoRoutines์„ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์—, ๊ธฐ๋‹ค๋ฆด ์ˆ˜ ์žˆ๊ณ , ์„œ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ฃผ๊ณ ๋ฐ›์„ ์ˆ˜ ์žˆ์–ด์•ผํ•œ๋‹ค. ๊ทธ๊ฑธ ์œ„ํ•ด ์กด์žฌํ•˜๋Š” ๊ฒƒ์ด Channel์ด๋‹ค.

Channels

Channel์€ GoRoutines์ด ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฐ’์„ ๋ฐ›์•„์ฃผ๋Š” ์—ญํ™œ์€ ํ•œ๋‹ค. callback ํ•จ์ˆ˜ ๊ฐ™์€ ๋Š๋‚Œ์ด์ง€๋งŒ ์•„๋‹Œ ๊ฒƒ ๊ฐ™๋‹ค. ์‚ฌ์šฉ๋ฒ•์€ ์‰ฝ๋‹ค. <-๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๊ณ  ๋ฐ›๋Š”๋‹ค.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
func main() {
	people := [4]string {"ksanbal", "hyunkyun", "hello", "world"}

	c := make(chan string) // string์„ ๋ฐ˜ํ™˜๋ฐ›๋Š” chan์ธ c๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

	for _, person := range people {
		go isSexy(person, c)
	}
	
	// ์‹คํ–‰์ด ์ข…๋ฃŒ๋˜๋Š”๋Œ€๋กœ ๋„˜์–ด์˜จ ๊ฐ’์„ ์ถœ๋ คํ•ด์ค€๋‹ค.
	result1 := <- c
	result2 := <- c
	fmt.Println(<-c)
	fmt.Println(<-c)
	fmt.Println(<-c) // ๋”์ด์ƒ ์ „๋‹ฌ๋ฐ›์„ ๊ฐ’์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— deadlock ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
}

func isSexy(person string, c chan string) {
	time.Sleep(time.Second * 5)
	c <- person + " is sexy"
}

๊ทธ๋Ÿฐ๋ฐ ์—ฌ๊ธฐ์„œ ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค. <-์€ blocking operation์ด๋‹ค. ์ฆ‰ ๊ฐ’์ด ์ „๋‹ฌ๋ ๋•Œ๊นŒ์ง€ ํ”„๋กœ๊ทธ๋žจ์ด ๋ฉˆ์ถฐ์„œ ๊ธฐ๋‹ค๋ฆฐ๋‹ค. ๊ทธ๋ฆฌ๊ณ  <- ์ด ์ „๋‹ฌ๋œ ๊ฒƒ๋ณด๋‹ค ๋” ๋งŽ์œผ๋ฉด deadlock ์—๋Ÿฌ๋ฅผ ๋ฐœ์ƒํ•œ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
func main() {
	people := [4]string {"ksanbal", "hyunkyun", "hello", "world"}

	c := make(chan string) // string์„ ๋ฐ˜ํ™˜๋ฐ›๋Š” chan์ธ c๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

	for _, person := range people {
		go isSexy(person, c)
	}
	
	for i:0; i<len(people); i++ {
		fmt.Println(<-c)
	}
}

func isSexy(person string, c chan string) {
	time.Sleep(time.Second * 5)
	c <- person + " is sexy"
}

์‚ฌ์‹ค ๋ณ„๊ฑด ์—†๊ณ  for๋ฌธ์œผ๋กœ GoRoutines์„ ์ƒ์„ฑํ•œ๋งŒํผ ๋Œ๋ ค์ฃผ๋ฉด ๋œ๋‹ค. <-c๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๊ฑฐ๋‹ˆ๊นŒ, for๋ฌธ ์ฒซ์ค„์— ๋„ฃ๊ณ  ๊ทธ ๋’ค์— callback ํ•จ์ˆ˜์ฒ˜๋Ÿผ ์ž‘์„ฑํ•˜๋ฉด ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค.

Send only & Recevie only

๊ทธ๋ฆฌ๊ณ  channel์€ send only์™€ receive only ์˜ต์…˜์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ ์œผ๋กœ ๋ฏธ๋ฆฌ ๊ธฐ๋Šฅ์„ ์ฐจ๋‹จํ•ด์„œ, ์ฝ”๋“œ ์ž‘์„ฑ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. <-์˜ ์œ„์น˜์— ๋”ฐ๋ผ ์ ์šฉ๋˜๋ฉฐ send only์—์„œ ๊ฐ’์„ ๋ฐ›์œผ๋ คํ•˜๋ฉด, vscode์—์„œ ๋ฏธ๋ฆฌ ๊ฒฝ๊ณ ๋ฅผ ๋‚ด์ค€๋‹ค.

1
2
3
4
5
6
7
8
9
// send only
func hitURL(url string, c chan<- requestResult) {
	...
}

// receive only
func hitURL(url string, c <-chan requestResult) {
	...
}

์ž์ž˜ํ•œ ๊ฒƒ

  1. ๋ฐฐ์—ด์€ ๋ฐฐ์—ด๋ช… ๋’ค์— ...์„ ์ด์šฉํ•ด์„œ ๋ชจ๋“  ์š”์†Œ๋ฅผ ๊บผ๋‚ผ ์ˆ˜ ์žˆ๋‹ค.
    1. append(jobs, []*string* {"police", "doctor", "teacher"}...)
Hugo๋กœ ๋งŒ๋“ฆ
Jimmy์˜ Stack ํ…Œ๋งˆ ์‚ฌ์šฉ ์ค‘