go 의 키워드 - select

31985 단어
1. select 의 사용
정의: golang 에서 select 의 기능 은 epoll (nginx) / poll / select 의 기능 과 유사 하 며, 모두 단단 한 IO 작업 입 니 다. IO 작업 이 발생 할 때 해당 하 는 동작 을 촉발 합 니 다.
1.1 일부 사용 규범
Go 의 언어 규범 에서 select 중의 case 의 실행 순 서 는 무 작위 입 니 다. 여러 개의 case 가 실 행 될 수 있 으 면 select 는 무 작위 로 실행 하 나 를 선택 하고 다른 것 은 실행 하지 않 습 니 다.
 1 package main
 2 
 3 import "fmt"
 4 
 5 func main() {
 6     ch := make (chan int, 1)
 7 
 8     ch1
 9     select {
10     case ch:
11         fmt.Println("   ")
12     case ch:
13         fmt.Println("   n")
14     }
15 }

출력 내용 은 무 작위 1, 2 안에 있 는 임의의 것 입 니 다.
case 뒤에 channel 작업 이 있어 야 합 니 다. 그렇지 않 으 면 오 류 를 보고 합 니 다.default 자 구 는 항상 실 행 될 수 있 기 때문에 default 의 select 가 없어 야 대기 이 벤트 를 막 을 수 있 습 니 다.실행 중인 케이스 가 없 으 면 이벤트 의 오 류 를 막 을 수 있 습 니 다.
1.2 select 의 응용 장면
timeout 메커니즘 (시간 초과 판단)
 1 package main
 2 
 3 import (
 4     "fmt"
 5     "time"
 6 )
 7 
 8 func main() {
 9     timeout := make (chan bool, 1)
10     go func() {
11         time.Sleep(1*time.Second) //   1s,    1s  I       ,  select     ~
12         timeout true
13     }()
14     ch := make (chan int)
15     select {
16     case  ch:
17     case  timeout:
18         fmt.Println("   !")
19     }
20 }

이렇게 쓸 수도 있다.
 1 package main
 2 
 3 import (
 4     "fmt"
 5     "time"
 6 )
 7 
 8 func main() {
 9     ch := make (chan int)
10     select {
11     case ch:
12     case 1): //   time   ,After             
13         fmt.Println("   !")
14     }
15 }

채널 이 막 혔 는 지 판단 하기 (혹은 채널 이 꽉 찼 는 지)
 1 package main
 2 
 3 import (
 4     "fmt"
 5 )
 6 
 7 func main() {
 8     ch := make (chan int, 1)  //          1
 9     ch 1
10     select {
11     case ch 2:
12     default:
13         fmt.Println("  channel    ,      !")
14     }
15 }

종료 메커니즘
 1 package main
 2 
 3 import (
 4     "fmt"
 5     "time"
 6 )
 7 
 8 func main() {
 9     i := 0
10     ch := make(chan string, 0)
11     defer func() {
12         close(ch)
13     }()
14 
15     go func() {
16         DONE: 
17         for {
18             time.Sleep(1*time.Second)
19             fmt.Println(time.Now().Unix())
20             i++
21 
22             select {
23             case m := ch:
24                 println(m)
25                 break DONE //    select   for   
26             default:
27             }
28         }
29     }()
30 
31     time.Sleep(time.Second * 4)
32     ch"stop"
33 }

2. select 의 실현
select - case 의 chan 작업 은 if - else 로 컴 파일 되 었 습 니 다.예:
1  select {
2  case v = c:
3          ...foo
4  default:
5          ...bar
6  }

다음 으로 컴 파일 됩 니 다:
1  if selectnbrecv(&v, c) {
2          ...foo
3  } else {
4          ...bar
5  }

유사 히
1  select {
2  case v, ok = c:
3      ... foo
4  default:
5      ... bar
6  }

다음 으로 컴 파일 됩 니 다:
1  if c != nil && selectnbrecv2(&v, &ok, c) {
2      ... foo
3  } else {
4      ... bar
5  }

selectnbrecv 함 수 는 runtime. chanrecv 함 수 를 간단하게 호출 할 뿐 인 자 를 설정 한 것 입 니 다. runtime. chanrecv 함수 가 완료 되 지 않 을 때 막 지 말고 되 돌아 오 는 데 실 패 했 음 을 알려 줍 니 다.즉, 모든 select 작업 은 사실 if - else 판단 으로 바 뀌 었 을 뿐 바 텀 에서 호출 되 는 차단 되 지 않 는 채널 조작 함수 로 바 뀌 었 다.
Go 의 언어 규범 에서 select 중의 case 의 실행 순 서 는 무 작위 입 니 다. 그러면 무 작위 로 어떻게 실현 합 니까?
select 와 case 키 워드 는 아래 구조 체 를 사 용 했 습 니 다:
1 struct    Scase
2   {
3       SudoG    sg;            // must be first member (cast to Scase)
4       Hchan*    chan;        // chan
5       byte*    pc;            // return pc
6       uint16    kind;
7       uint16    so;            // vararg of selected bool
8       bool*    receivedp;    // pointer to received bool (recv2)
9   };
1  struct    Select
2      {
3      uint16    tcase;            //   scase[]  
4      uint16    ncase;            //       scase[]  
5      uint16*    pollorder;        // case poll  
6      Hchan**    lockorder;        // channel      
7      Scase    scase[1];        //   case         Scase,         
8  };

모든 select 는 하나의 Select 구조 체 에 대응 합 니 다.Select 데이터 구조 에 Scase 배열 이 있 고 모든 case 를 기록 하 며 Scase 에는 Hchan 이 포함 되 어 있 습 니 다.그리고 pollorder 배열 은 요 소 를 무 작위 로 배열 하면 Scase 를 어 지 럽 힐 수 있 습 니 다.
 3. 자물쇠 선택
select 가 주의 하지 않 아 도 잠 금 이 발생 합 니 다. 두 가지 상황 으로 나 눌 수 있 습 니 다.
전송 할 데이터 가 없 으 면 select 에 채널 데 이 터 를 받 는 문구 가 존재 합 니 다. 그러면 잠 금 을 보 냅 니 다.
1 package main
2 func main() {  
3     ch := make(chan string)
4     select {
5     case ch:
6     }
7 }

예방 하면 default.
빈 select 도 잠 금 을 일 으 킬 수 있 습 니 다.
1 package main
2 
3 func main() {  
4     select {}
5 }

 4. select 와 switch 의 차이
select
select 는 channel 의 작업 에 만 적용 할 수 있 습 니 다. channel 의 데이터 수신 도 할 수 있 고 channel 의 데이터 전송 도 할 수 있 습 니 다.만약 에 select 의 여러 가지 가 조건 을 만족 시 키 면 그 중의 만족 조건 의 가 지 를 무 작위 로 선택 할 것 입 니 다. 예 를 들 어 규범 에서 말 한 것 처럼:
If multiple cases can proceed, a uniform pseudo-random choice is made to decide which single communication will execute.

'case' 문장의 표현 식 은 하나의 변수 나 두 개의 변수 에 값 을 부여 할 수 있 습 니 다.default 문장 이 있 습 니 다.
31 package main                                                                                                                                              32 import "time"
33 import "fmt"                                                                                                                                              
35 func main() {                                                                                                                                             36     c1 := make(chan string)
37     c2 := make(chan string)                                                                                                                               38     go func() {
39         time.Sleep(time.Second * 1)                                                                                                                       40         c1 "one"
41     }()                                                                                                                                                   42     go func() {
43         time.Sleep(time.Second * 2)                                                                                                                       44         c2 "two"
45     }()                                                                                                                                                   46     for i := 0; i < 2; i++ {
47         select {                                                                                                                                          48             case msg1 := c1:
49             fmt.Println("received", msg1)          
50 case msg2 := c2: 51 fmt.Println("received", msg2)
52 } 53 }

switch
switch 는 다양한 유형 에 대해 분기 작업 을 할 수 있 으 며 인터페이스 유형 에 대해 분기 판단 을 할 수 있 습 니 다 (i. (type).switch 가 지 는 순서대로 실 행 됩 니 다. 이것 은 select 와 다 릅 니 다.
 1 package main                  
 2 import "fmt"
 3 import "time"  
 4 
 5 func main() {                                                                                                                             
 6      i := 2
 7      fmt.Print("Write ", i, " as ")  
 8      switch i {
 9          case 1:
10          fmt.Println("one")
11          case 2:                                                                                                                                  
12          fmt.Println("two")
13          case 3:                                                                                                                      
14          fmt.Println("three")
15      }                                                                                                                                             
16      switch time.Now().Weekday() {
17          case time.Saturday, time.Sunday:
18          fmt.Println("It's the weekend")
19          default:                                                                                                                                      
20          fmt.Println("It's a weekday")
21      }                                                                                                                                                 
22      t := time.Now()
23      switch {                                                                                                                                         
24          case t.Hour() < 12:
25          fmt.Println("It's before noon")                                                                                                              
26          default:
27          fmt.Println("It's after noon")                                                                                                                  
28      }
29      whatAmI := func(i interface{}) {                                                                                                                   
30          switch t := i.(type) {
31              case bool:                                                                                                                              
32              fmt.Println("I'm a bool")
33              case int:                                                                                                                                 
34              fmt.Println("I'm an int")
35              default:                                                                                                                                 
36              fmt.Printf("Don't know type %T
", t) 37 } 38 } 39 whatAmI(true) 40 whatAmI(1) 41 whatAmI("hey") 42 }

좋은 웹페이지 즐겨찾기