English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
В языке Go канал является средством передачи данных между 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("\nЗначение channel1:", mychannel1) fmt.Printf("Тип channel1: %T", mychannel1) }
Вывод:
Значение channel: <nil> Тип channel: chan int Значение channel1: 0xc0000160c0 Тип channel1: chan int
В языке Go работа каналов имеет два основных действия: отправка и接收, которые в совокупности называются коммуникацией. Направление оператора <- указывает на то, идет ли передача данных или их прием. По умолчанию, отправка и прием данных блокируются до тех пор, пока на другом конце канала нет данных. Это позволяет goroutine синхронизироваться друг с другом без использования явных блокировок или переменных условия.
Операция отправки:Операция отправки используется для передачи данных из одного goroutine в другое при помощи канала. Значения, такие как int, float64 и bool, могут быть безопасно и легко отправлены через канал, так как они копируются, и не существует риска случайного параллельного доступа к одному и тому же значению. Также, строки безопасны, так как они не изменяются. Однако, отправка через канал указателей или ссылок (например, массивов, множеств и т.д.) не безопасна, так как значения указателей или ссылок могут изменяться параллельно отправляющим или получающим goroutine, и результат может быть непредсказуемым. Поэтому, при использовании указателей или ссылок в канале, необходимо обеспечить, чтобы они могли быть доступны только одному goroutine за один раз.
Mychannel <- element
Указанное выше предложение означает, что данные (element) были отправлены в<-оператор помогает отправлять данные в канал (Mychannel).
операция получения:операция получения используется для получения данных, отправленных отправителем.
element := <-Mychannel
Указанное выше предложение означает, что элемент был получен из канала (Mychannel). Если полученное значение не доступно для использования (не нужно использовать), это также является эффективным предложением. Вы также можете написать следующее предложение получения:
<-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(). Это вbuilt функция, которая устанавливает индикатор, что больше не будут отправляться значения в канал.
Синтаксис:
close()
Вы также можете использовать цикл range для закрытия канала. В данном случае, приемник 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) прервать } fmt.Println("Открытие канала ", res, ok) } }
Вывод:
Открытие канала w3codebox true Открытие канала w3codebox true Открытие канала w3codebox true Открытие канала w3codebox true Закрытие канала false
Блокировка отправки и приема:В каналах, когда данные отправляются в канал, контроль в блоке отправки блокируется до тех пор, пока другой goroutine не начнет чтение данных из этого канала. Аналогично, когда канал принимает данные от goroutine, блок чтения ожидает, пока другое goroutine не выполнит команду.
Нулевой канал: каналнулевое значение 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
Длина канала:В каналах вы можете использоватьФункция 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 в каналах:В языке Go, оператор select resembles a switch statement without any input parameters. The select statement is used in channels to execute a single operation from multiple operations provided by case blocks.