Server/Go

Go) 동시작업 Goroutines

Juzdalua 2022. 11. 23. 16:18

Go는 다른 언어와 마찬가지로 Top-Down 방식으로 동기화처럼 작업이 끝나고 다음 코드를 수행한다.

 

package main

import (
	"fmt"
	"time"
)

func main() {
	countName("jun")
	countName("JUN")
}

func countName(name string) {
	for i := 0; i < 5; i++ {
		fmt.Println(name)
		time.Sleep(time.Second * 1)
	}
}

위처럼 수행하면 코드 1줄 당 1초, 총 10초가 걸린다.

Go는 비동기화처럼 동시작업을 위해 사용하는 언어라고 알고있다.

 

JS의 async/await처럼 Go에서도 go라는 명령어로 비슷하게 작업을 수행할 수 있다.

 

package main

import (
	"fmt"
	"time"
)

func main() {
	go countName("jun")
	countName("JUN")
}

func countName(name string) {
	for i := 0; i < 5; i++ {
		fmt.Println(name)
		time.Sleep(time.Second * 1)
	}
}

 

Goroutine은 메인 함수가 종료되면 함께 종료된다.

다시 말해, 프로그램이 실행 되는 동안에만 유효하다.

 

Goroutine은 리턴을 반환하지 않는다.

package main

import (
	"fmt"
	"time"
)

func main() {
	go countName("jun")
	result := go countName("JUN")
	fmt.Println(result)
}

func countName(name string) bool {
	time.Sleep(time.Second * 5)
	return true
}

위와 같은 코드에서 result := go countName()에 에러가 발생한다.

이를 해결하기 위해 채널을 사용한다.

 

package main

import (
	"fmt"
	"time"
)

func main() {
	// start immediately
	c := make(chan bool)
	go countName("JUN", c)

	// go runtime is stop. wait until get channel message
	result := <-c

	fmt.Println(result)
}

func countName(name string, c chan bool) {
	time.Sleep(time.Second * 1)
	c <- true
}

메인에서 channel을 만든다.

countName 함수에 값을 받을 채널을 함께 파라미터로 보낸다.

countName 함수에서 채널에 결과값을 저장한다.

메인에서 채널 메세지를 받아온다.

 

채널메세지가 여러개일 경우 Go는 인식한다.

package main

import (
	"fmt"
	"time"
)

func main() {
	// start immediately
	c := make(chan bool)
	people := []string{"jun", "JUN"}

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

	// go runtime is stop. wait until get channel message
	fmt.Println(<-c)
	fmt.Println(<-c)
}

func countName(name string, c chan bool) {
	time.Sleep(time.Second * 5)
	c <- true
}

 

채널을 받는 함수에서는 변수명 chan 채널의리턴타입을 파라미터로 받는다.

채널에 값을 저장하고 채널 메세지를 불러올 때는 <- 연산자를 사용한다.

 

메인에서 채널 값을 받아올 때는 해당 값을 불러올 때까지 메인함수는 기다려준다.