func ex1() {
fmt.Println("exe1 func start", time.Now())
time.Sleep(1 * time.Second)
fmt.Println("exe1 func end", time.Now())
}
func main(){
fmt.Println("main routine start", time.Now())
// 실행시킬 subroutine에 go 만 앞에 붙여주면 됨
go ex1() // go routine : sub-routine
fmt.Println("main routine end", time.Now())
}
// runtime.NumCPU() : CPU 갯수 구함
// runtime.GOMAXPROCS: 구한 CPU 갯수를 GO처리에 사용할 최대 CPU 갯수로 할당
runtime.GOMAXPROCS(runtime.NumCPU())
// runtime.GOMAXPROCS 인자로 전달된 cpu 갯수를 셋팅하고 이전 값을 반환. 인자값이 < 1 인 경우, 이전 설정을 그대로 사용
fmt.Println("current system CPU :", runtime.GOMAXPROCS(0)) // 설정값 출력
고루틴 클로저는 반복문 종료 후 실행되므로 인자 전달에 유의해야한다.
s := "closure test"
for i := 0; i < 1000; i++ {
// 즉시 실행 함수로 인자를 넘기지 않으면
// 반복문이 끝난 시점에 i가 999가 된 상태 값이 전달되어 999만 999번 생성된다.
go func() {
fmt.Println(s, i, " - ", time.Now())
}()
// 인자로 전달한 시점에 i가 값 복사 되므로 나중에 실행되도 문제 없음
go func(n int) {
fmt.Println(s, n, " - ", time.Now())
}(i)
}
wg := new(sync.WaitGroup)
for i := 0; i < 100; i++ {
wg.Add(1)
go func(n int) {
fmt.Println("wait Group : ", n)
wg.Done()
}(i)
}
// Add == Done 횟수 같아야 함
wg.Wait()
fmt.Println("WaitGroup end!")
<- : 수신 (변수 <- 채널)
-> : 송신 (데이터 -> 채널)
func work1(v chan int) {
fmt.Println("work1 : s --> ", time.Now())
time.Sleep(1 * time.Second)
fmt.Println("work1 : E --> ", time.Now())
v <- 1
}
func work2(v chan int) {
fmt.Println("work2 : s --> ", time.Now())
time.Sleep(1 * time.Second)
fmt.Println("work2 : E --> ", time.Now())
v <- 2
}
v := make(chan int) // int형 채널 선언. 채널은 참조형
go work1(v)
go work2(v)
// 먼저 수신된 순서대로 출력됨. 하나 송신되면 하나 수신 할수있음
fmt.Println(<-v)
fmt.Println(<-v)
// 수신할 데이터가 없는데 수신을 기다리면 데드락 발생
// fmt.Println(<-v)
채널의 버퍼 용량이 full이 될 때가지 기다렸다가 가득 차면 한꺼번에 내보냄
// channel의 용량을 3로 설정
// 3개 보낸 후 한꺼번에 3개 받기
ch := make(chan bool, 3)
ch := make(chan bool)
go func() {
for i := 0; i < 5; i++ {
ch <- true
}
close(ch) // 5회 채널에 값 전송 후 채널 닫기
}()
// 채널에서 값을 꺼내온다.
// 채널이 close 될 때 까 계속 대기. close가 되지 않으면 무한 대기
for i := range ch {
fmt.Println("ex 1 :", i)
}
ch := make(chan string)
go func() {
for i := 0; i < 2; i++ {
ch <- "go"
}
}()
val1, ok1 := <-ch
fmt.Println("ex1 : ", val1, ok1)
val2, ok2 := <-ch
fmt.Println("ex1 : ", val2, ok2)
close(ch)
val3, ok3 := <-ch
// 채널 수신 시 받는 두번째 인자인 ok3 값으로 채널 닫힘 유무를 알수있음
fmt.Println(val3, ok3)
func sendOnly(c chan<- int, cnt int) {
for i := 0; i < cnt; i++ {
c <- i
}
c <- 777
// 입력받은 파라미터 c는 송신 전용 채널이기 때문에 수신 불가
//fmt.Println(<-c)
}
func receiveOnly(c <-chan int) {
for i := range c {
fmt.Println("received : ", i)
}
fmt.Println(<-c)
}
c := make(chan int)
go sendOnly(c, 10) // 송신전용 (데이터 -> 채널)
go receiveOnly(c) // 수신전용 (데이터 <- 채널)
ch1 := make(chan int)
ch2 := make(chan string)
go func() {
for {
ch1 <- 77
time.Sleep(250 * time.Millisecond)
}
}()
go func() {
for {
ch2 <- "go hi~"
time.Sleep(250 * time.Millisecond)
}
}()
go func() {
for {
select {
case num := <-ch1:
fmt.Println("ch1 : ", num)
case str := <-ch2:
fmt.Println("ch2 : ", str)
// default:
// fmt.Println("default")
}
}
}()
[학습 자료] 인프런 - 쉽고 빠르게 끝내는 GO언어 프로그래밍 핵심 기초 입문 과정
[공식사이트] https://golang.org/tutorial