非同期 - Go

最終更新日: 2026-07-25

TOP(About this memo)) > 一覧(Go) > 非同期

Goroutines (ゴルーチン)

go func() {
    ////
}()

チャネル

生成

// all goroutines are asleep - deadlock!
func main() {
	var syn chan interface{}
	go func() {
		syn <- struct{}{}
		fmt.Println("g1 end")
	}()
	<-syn
}
fmt.Println("main start")
	syn := make(chan interface{}, 0)
	syn <- struct{}{}//これが送信できないのでロック。
	fmt.Println("main end")

送信

受信

自分で送信したものも受け取れる。

syn := make(chan int, 1)
syn <- 5
print(<-syn)// 5

受信(select)

バッファ

close

range

送信専用、受信専用

// ch 送信専用
func test1(ch chan<- string, wg *sync.WaitGroup) {
	defer wg.Done()
	ch <- "aaaa"
}

// ch 受信専用
func test2(ch <-chan string, wg *sync.WaitGroup) {
	defer wg.Done()
	m := <-ch
	fmt.Println(m)
}

サンプルコード

package main

import (
	"fmt"
	"time"
)

func chtest(ch chan interface{}) {
	fmt.Println("chtest running")
	time.Sleep(time.Second * 3)
	ch <- struct{}{}
	fmt.Println("chtest end")
}

func chtest2(ch chan interface{}) {
	defer close(ch)
	fmt.Println("chtest2 running")
	time.Sleep(time.Second * 3)
	fmt.Println("chtest2 end")
}

func chtest3(ch chan interface{}) {
	fmt.Println("chtest3 running")
	time.Sleep(time.Second * 3)
	fmt.Println("chtest3 end")
}

func chtest4(ch chan interface{}) {
	fmt.Println("chtest4 running")
	time.Sleep(time.Second * 3)
	ch <- 1
	fmt.Println("chtest4 end")
}

func main() {
	ch := make(chan interface{}, 1)
	fmt.Println("chtest call")
	go chtest(ch)
	v, ok := <-ch
	fmt.Println(v)
	fmt.Println(ok)

	/*
		// goroutineがすべて終了にしているのでデッドロックとなるためpanicになる。
		v, ok = <-ch 
		fmt.Println(v)
		fmt.Println(ok)
	*/

	//chはcloseしなければ使いまわしできる。
	fmt.Println("chtest call again")
	go chtest(ch)
	v, ok = <-ch
	fmt.Println(v)
	fmt.Println(ok)

	//closeされた場合はcloseしたタイミングでvはnil、okはfalseを受け取る。
	fmt.Println("chtest2 call")
	go chtest2(ch)
	v, ok = <-ch
	fmt.Println(v)
	fmt.Println(ok)

	/*
		// これはpanicになる。chがcloseしているのに、chtest2の最後に再度closeをしようとするから。
		fmt.Println("chtest2 call again")
		go chtest2(ch)
		v, ok = <-ch // これはすぐに後続へ進む。なぜならchはcloseされているから。
		fmt.Println(v)
		fmt.Println(ok)
	*/

	ch2 := make(chan interface{}, 1)
	/*
		//panicになる。chtest3ではチャネル送信をしていないため、待ち状態のまま(デッドロック)してしまうため。
		fmt.Println("chtest3 call")
		go chtest3(ch2)
		v, ok = <-ch2
		fmt.Println(v)
		fmt.Println(ok)
	*/

	fmt.Println("chtest4 call")
	go chtest4(ch2)
	v, ok = <-ch2
	fmt.Println(v)
	fmt.Println(ok)
}

排他制御(Mutex)

context

注意点

Value

サーバーでの使い方

sleep と go routine

func main() {
	for i := 0; i < 100; i++ {
		a := 0
		var wg sync.WaitGroup
		wg.Add(1)
		go func() {
			a = 1
			wg.Done()
		}()
		wg.Add(1)
		go func() {// 必ずこっちが後に終わる。
			time.Sleep(time.Microsecond * 1)
			a = 2
			wg.Done()
		}()
		wg.Wait()
		fmt.Print(a)
	}

}

sync

// You can edit this code!
// Click here and start typing.
package main

import (
	"fmt"
	"sync"
	"time"
)

func main() {
	fmt.Println("main start")

	syn := make(chan interface{}, 1)
	var wg sync.WaitGroup

	wg.Add(1)
	go func() {
		fmt.Println("g1 start")
		fmt.Println("g1 waiting...")
		<-syn
		time.Sleep(time.Millisecond * 1000)
		fmt.Println("g1 exec done")
		syn <- struct{}{}
		fmt.Println("g1 end")
		wg.Done()
	}()

	wg.Add(1)
	go func() {
		fmt.Println("g2 start")
		time.Sleep(time.Millisecond * 1000)
		fmt.Println("g2 exec done")
		syn <- struct{}{}
		fmt.Println("g2 waiting...")
		<-syn
		fmt.Println("g2 end")
		wg.Done()
	}()

	wg.Wait()
	fmt.Println("main end")

/*

main start
g2 start
g1 start
g1 waiting...
g2 exec done
g2 waiting...
g1 exec done
g1 end
g2 end
main end

*/

}