English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Golang 基础教程

Golang 控制语句

Golang 函数 & 方法

Golang 结构体

Golang 切片 & 数组

Golang 字符串(String)

Golang 指针

Golang 接口

Golang 并发

Golang 异常(Error)

Golang 其他杂项

Go 언어 채널(Channel)

고어 언어에서 채널은 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들이 명시적인 락이나 조건 변수 없이 서로 동기화할 수 있게 합니다.

  1. 전송 작업:채널을 통해 데이터를 하나의 goroutine에서 다른 goroutine로 전송하는 데 사용되는 전송 작업입니다. int, float와 같은64bool와 같은 값들은 복사되기 때문에 안전하고 쉽게 채널을 통해 전송할 수 있습니다. 따라서 동시에 같은 값을 접근하는 경우 예상치 못한 동기화 문제가 발생할 위험이 없습니다. 마찬가지로 문자열도 안전합니다. 문자열은 불변적이기 때문입니다. 하지만, 포인터나 참조(예: 슬라이스, 맵 집합 등)를 채널을 통해 전송하는 것은 안전하지 않습니다. 포인터나 참조의 값은 동시에 전송되는 goroutine이나 수신하는 goroutine에 의해 변경될 수 있으며, 결과는 예측할 수 없습니다. 따라서 채널에서 포인터나 참조를 사용할 때는 그것이 한 번에 단일 goroutine에만 접근할 수 있도록 해야 합니다.

    Mychannel <- element

    上面的语句表明数据(element)在<-运算符的帮助下发送到通道(Mychannel)。

  2. 接收操作:接收操作用于接收发送操作方发送的数据。

    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 블록에서 제공된 여러 작업 중 하나를 실행합니다.