package main
import("fmt""time")functestGoRoutine(routine_num int){
for i :=1; i <5; i++{
fmt.Printf("routine_num is %d ; i is %d\n", routine_num, i)
time.Sleep(10* time.Millisecond)}}funcmain(){
gotestGoRoutine(1)gotestGoRoutine(2)
time.Sleep(100* time.Millisecond)}// routine_num is 1 ; i is 1//routine_num is 2 ; i is 1//routine_num is 2 ; i is 2//routine_num is 1 ; i is 2//routine_num is 1 ; i is 3//routine_num is 2 ; i is 3//routine_num is 2 ; i is 4//routine_num is 1 ; i is 4
2: 채널
역할: 하나의 고루틴이 다른 고루틴과 통신할 수 있게 해주는 채널입니다.
채널 정의: pipline := make(chan 채널 유형)
채널 닫힘: 닫기(파이프라인)
채널에 데이터 보내기: pipline<- data
채널에서 데이터 가져오기: mydata := <-pipline
채널을 닫은 후에도 수신자는 여전히 채널에서 데이터를 가져올 수 있지만 수신된 데이터는 항상 0입니다.
채널에서 데이터를 읽을 때 여러 반환 값이 있을 수 있으며 두 번째 반환 값은 채널이 닫혔는지 여부를 나타낼 수 있습니다. 닫혀 있으면 ok는 false이고 닫히지 않으면 ok는 true입니다.
x, 확인 := <-파이프라인
버퍼링 및 버퍼링되지 않은 채널
버퍼링되지 않은 채널
특징: 받는 쪽이 보내는 쪽보다 먼저 준비가 되어 있어야 합니다.
버퍼링된 채널
2.1: 채널의 간단한 사용
package main
import"fmt"// 发送信息到信道中funcsend_data(pipline chanint, data int){
pipline <- data
}// 在信道中获取信息funcget_data(pipline chanint)int{
return<-pipline
}funcmain(){
// 定义一个信道
pipline :=make(chanint)gosend_data(pipline,200)
resData :=get_data(pipline)
fmt.Println(resData)}// 200
2.2: 단방향 채널
package main
import("fmt""time")// Sender 定义只写信道类型type Sender =chan<-int// Receiver 定义只读信道类型type Receiver =<-chanintfuncmain(){
var pipline =make(chanint)gofunc(){
var sender Sender = pipline
fmt.Println("准备发送数据: 100")
sender <-100}()gofunc(){
var receiver Receiver = pipline
num :=<-receiver
fmt.Printf("接收到的数据是: %d", num)}()// 主函数sleep,使得上面两个goroutine有机会执行
time.Sleep(time.Second)}
2.3: 횡단 채널
채널을 통과하려면 채널이 닫혀 있는지 확인하십시오. 그렇지 않으면 루프가 차단됩니다.
package main
import"fmt"funcaddDataToChan(myChan chanint){
for i :=1; i <=5; i++{
myChan <- i
}// 关闭信道close(myChan)}funcmain(){
// 定义一个信道
myChan :=make(chanint,5)// 信道中加入值, 然后关闭信道addDataToChan(myChan)// 遍历信道for myChanData :=range myChan {
fmt.Printf("myChan is %d\n", myChanData)}}//myChan is 1//myChan is 2//myChan is 3//myChan is 4//myChan is 5
2.4: 잠금으로서의 채널
package main
import("fmt""time")funcincrement(ch chanbool, x *int){
// 当前协程在信道存上值,其他的协程就一直阻塞中。
ch <-true*x =*x +1<-ch
}funcmain(){
// 注意要设置容量为 1 的缓冲信道
pipline :=make(chanbool,1)var x intfor i :=0; i <1000; i++{
goincrement(pipline,&x)}
time.Sleep(time.Second)
fmt.Println("x 的值:", x)}
셋: select-case의 사용법
사용 범위: 채널 사용만 지원
기능: select를 실행할 때 데이터를 수신한 채널이 있는 한 모든(가능한 경우) case 표현식을 통과한 다음 select가 종료됩니다.
기능: select의 경우는 순차적이 아닌 무작위로 실행됩니다.
참고: default 문을 작성해 보세요. 작성하지 않고 대소문자가 맞지 않으면 예외가 발생합니다.
기본 사용 사례:
package main
import("fmt""sync")// 定义两个信道,开两个协程, 往信道中追加数据, 测试结果。funcsendDataToChan(inputChan chanint, inputData int, wg *sync.WaitGroup){
defer wg.Done()
inputChan <- inputData
}funcmain(){
chan01 :=make(chanint,1)
chan02 :=make(chanint,1)var wg sync.WaitGroup
wg.Add(2)gosendDataToChan(chan01,1,&wg)gosendDataToChan(chan02,2,&wg)
wg.Wait()select{
case outData :=<-chan01:
fmt.Printf("outData is %d\n", outData)case outData :=<-chan02:
fmt.Printf("outData is %d\n", outData)default:
fmt.Printf("no data\n")}}//outData is 2//outData is 1
package main
import("context""fmt""time")funcmonitor(ctx context.Context, number int){
for{
select{
// 上下文关闭case v :=<-ctx.Done():
fmt.Printf("监控器%v,接收到通道值为:%v,监控结束。\n", number, v)returndefault:
fmt.Printf("监控器%v,正在监控中...\n", number)
time.Sleep(2* time.Second)}}}funcmain(){
// 实例化上下文
ctx, cancel := context.WithCancel(context.Background())// 开启多个协程for i :=1; i <=5; i++{
gomonitor(ctx, i)}
time.Sleep(1* time.Second)// 关闭所有 goroutinecancel()
time.Sleep(5* time.Second)
fmt.Println("主程序退出!!")}
6: WaitGroup
기능: 주요 기능으로, 실행하기 전에 많은 코루틴이 완료될 때까지 기다립니다.
기능: 코루틴 간의 흐름 제어에 사용됩니다.
package main
import("fmt""sync")funcworker(x int, wg *sync.WaitGroup){
// 计数器 -1defer wg.Done()for i :=0; i <5; i++{
fmt.Printf("worker %d: %d\n", x, i)}}funcmain(){
var wg sync.WaitGroup
// 计数器 +2
wg.Add(2)goworker(1,&wg)goworker(2,&wg)//阻塞, 直到计数器归0
wg.Wait()}
7: 뮤텍스 잠금 및 읽기-쓰기 잠금
뮤텍스:
package main
import("fmt""sync")funcadd(count *int, wg *sync.WaitGroup, lock *sync.Mutex){
lock.Lock()*count =*count +1
lock.Unlock()
wg.Done()}funcmain(){
var wg sync.WaitGroup
// 定义一个互斥锁
lock :=&sync.Mutex{
}
count :=0
wg.Add(10000)// 开1000个协程for i :=1; i <=10000; i++{
goadd(&count,&wg, lock)}
wg.Wait()
fmt.Println("count 的值为:", count)}//count 的值为: 10000