English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
고어 언어에서 채널은 goroutine와 다른 goroutine 간의 통신 매개체이며, 이 통신은 락 없는 통신입니다. 다시 말해, 채널은 하나의 goroutine가 데이터를 다른 goroutine에 전송할 수 있는 기술입니다. 기본적으로 채널은 양방향입니다. 이는 goroutine가 동일한 채널을 통해 데이터를 전송하거나 수신할 수 있다는 것을 의미합니다. 다음 그림과 같이 보입니다:
Go 언어에서 chan 키워드를 사용하여 채널을 생성하며, 이 채널은 동일한 타입의 데이터만 전송할 수 있으며, 동일한 채널을 통해 다른 타입의 데이터를 전송할 수 없습니다.
문법:
var Channel_name chan Type
make() 함수를 사용하여 간단히 채널을 생성할 수도 있습니다.
문법:
channel_name:= make(chan Type)
package main import "fmt" func main() { //var 키워드를 사용하여 채널을 생성합니다 var mychannel chan int fmt.Println("channel의 값: ", mychannel) fmt.Printf("channel的类型: %T ", mychannel) // make() 함수를 사용하여 채널을 생성합니다 mychannel1 := make(chan int) fmt.Println("\nchannel1의 값:", mychannel1) fmt.Printf("channel1의 타입: %T ", mychannel1) }
출력:
채널의 값: <nil> 채널의 타입: chan int 채널1의 값: 0xc0000160c0 채널1의 타입: chan int
Go 언어에서 채널은 주로 두 가지 작업을 수행합니다. 하나는 전송, 다른 하나는 수신입니다. 이 두 작업은 통합하여 통신으로 불립니다.<-연산자의 방향은 데이터를 수신하거나 전송하는지를 나타냅니다. 채널에서는 기본적으로, 데이터가 다른 쪽에 없을 때까지 전송이나 수신 작업이 블록됩니다. 이는 goroutine들이 명시적인 락이나 조건 변수 없이 서로 동기화할 수 있게 합니다.
전송 작업:채널을 통해 데이터를 하나의 goroutine에서 다른 goroutine로 전송하는 데 사용되는 전송 작업입니다. int, float와 같은64bool와 같은 값들은 복사되기 때문에 안전하고 쉽게 채널을 통해 전송할 수 있습니다. 따라서 동시에 같은 값을 접근하는 경우 예상치 못한 동기화 문제가 발생할 위험이 없습니다. 마찬가지로 문자열도 안전합니다. 문자열은 불변적이기 때문입니다. 하지만, 포인터나 참조(예: 슬라이스, 맵 집합 등)를 채널을 통해 전송하는 것은 안전하지 않습니다. 포인터나 참조의 값은 동시에 전송되는 goroutine이나 수신하는 goroutine에 의해 변경될 수 있으며, 결과는 예측할 수 없습니다. 따라서 채널에서 포인터나 참조를 사용할 때는 그것이 한 번에 단일 goroutine에만 접근할 수 있도록 해야 합니다.
Mychannel <- element
上面的语句表明数据(element)在<-运算符的帮助下发送到通道(Mychannel)。
接收操作:接收操作用于接收发送操作方发送的数据。
element := <-Mychannel
上面的语句表明该元素从channel(Mychannel)接收数据。如果接收到的语句的结果不可用(不需要使用),则也是有效的语句。您还可以编写如下的receive语句:
<-Mychannel
package main import "fmt" func myfunc(ch chan int) { fmt.Println(234 + <-ch) } func main() { fmt.Println("主方法开始") //创建通道l ch := make(chan int) go myfunc(ch) ch <- 23 fmt.Println("主方法结束") }
출력:
主方法开始 257 主方法结束
您也可以在close()函数的帮助下关闭通道。这是一个内置函数,并设置一个标识,表示不再有任何值将发送到该通道。
문법:
close()
您也可以使用for范围循环关闭通道。在这里,接收器goroutine可以借助给定的语法检查通道是打开还是关闭:
ele, ok:= <- Mychannel
在此,如果ok的值为true,则表示通道已打开,因此可以执行读取操作。并且,如果的值为false,则表示该通道已关闭,因此将不执行读取操作。
//Go程序说明如何 //关闭使用的通道 //range循环和关闭函数 package main import "fmt" func myfun(mychnl chan string) { for v := 0; v < 4; v++ { mychnl <- "w3codebox" } close(mychnl) } func main() { //创建通道 c := make(chan string) // 使用 Goroutine go myfun(c) //当ok的值为true时,表示通道已打开,可以发送或接收数据 //当ok的值设置为false时,表示通道已关闭 for { res, ok := <-c if ok == false { fmt.Println("채널 닫힘", ok) break } fmt.Println("채널 열림", res, ok) } }
출력:
채널 열림 w3codebox true 채널 열림 w3codebox true 채널 열림 w3codebox true 채널 열림 w3codebox true 채널 닫힘 false
전송과 수신 차단:채널에서 데이터가 채널에 전송될 때, send 문에서 블록이 되어 다른 goroutine가 해당 채널에서 데이터를 읽을 때까지 대기합니다. 마찬가지로, 채널이 goroutine에서 데이터를 받을 때, read 문 블록이 다른 goroutine가 채널에서 데이터를 전송할 때까지 계속됩니다.
null 채널: 채널의 null 값은 nil입니다.
채널의 for 루프: for 루프는 채널에 전송된 순서 값을 순회할 수 있으며, 닫힘 직전까지 계속됩니다.
문법:
for item := range Chnl { // 문장.. }
package main import "fmt" func main() { // make() 함수를 사용하여 채널을 생성합니다 mychnl := make(chan string) // 익명 goroutine go func() { mychnl <- "GFG" mychnl <- "gfg" mychnl <- "Geeks" mychnl <- "w3codebox" close(mychnl) } //for 루프를 사용합니다 for res := range mychnl { fmt.Println(res) } }
출력:
GFG gfg Geeks w3codebox
채널 길이:채널에서 cap() 함수를 사용하여len() 함수채널 길이를 찾습니다. 여기서 길이는 채널 버퍼에 대기하는 값의 수를 의미합니다.
package main import "fmt" func main() { // make() 함수를 사용하여 채널을 생성합니다 mychnl := make(chan string, 4) mychnl <- "GFG" mychnl <- "gfg" mychnl <- "Geeks" mychnl <- "w3codebox" // len() 함수를 사용하여 채널 길이를 찾습니다 fmt.Println("채널 길이:", len(mychnl)) }
출력:
채널 길이: 4
채널 용량:채널에서 cap() 함수를 사용하여 채널 용량을 찾을 수 있습니다. 여기서 용량은 버퍼의 크기를 의미합니다.
package main import "fmt" func main() { // make() 함수를 사용하여 채널을 생성합니다 mychnl := make(chan string, 4) mychnl <- "GFG" mychnl <- "gfg" mychnl <- "Geeks" mychnl <- "w3codebox" // cap() 함수를 사용하여 채널 용량을 찾습니다 fmt.Println("채널 용량:", cap(mychnl)) }
출력:
채널 용량: 5
채널의 Select와 case 문:고(고) 언어에서 select 문은 입력 파라미터가 없는 switch 문과 유사합니다. 채널에서 select 문을 사용하여 case 블록에서 제공된 여러 작업 중 하나를 실행합니다.