go 의 키워드 - 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 }
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.