Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Teknik pemprosesan saluran tak segerak dalam bahasa Go

Teknik pemprosesan saluran tak segerak dalam bahasa Go

WBOY
WBOYasal
2023-06-03 15:31:341332semak imbas

Saluran (saluran) tak segerak ialah salah satu ciri yang sangat penting dalam bahasa Go, yang membolehkan kami berkomunikasi dan menyegerakkan antara goroutin. Kaedah komunikasi ini sangat cekap dan lebih selamat daripada memori kongsi kerana operasi baca/tulis pada memori kongsi memerlukan penguncian eksplisit untuk mengelakkan keadaan perlumbaan. Dalam artikel ini, kita akan membincangkan beberapa teknik biasa yang digunakan dalam pengendalian saluran tak segerak.

  1. Saluran buffered

Saluran buffered ialah saluran tak segerak yang boleh menampan beberapa elemen tertentu antara operasi penghantaran dan penerimaan, supaya Pihak tidak perlu menunggu pihak yang menerima. Dalam erti kata lain, saluran penimbal membenarkan coroutine berkomunikasi secara tidak segerak.

Sebagai contoh, berikut ialah contoh penggunaan saluran penimbal:

package main

import "fmt"

func main() {
    ch := make(chan int, 2) // 创建缓冲信道,缓存两个元素
    ch <- 1
    ch <- 2
    fmt.Println(<-ch) // 从信道中读取第一个元素
    fmt.Println(<-ch) // 从信道中读取第二个元素
}

Outputnya ialah:

1
2

Dalam contoh di atas, kami mencipta saluran penimbalch , cache dua elemen integer. Kemudian kami menggunakan dua pernyataan ch <- 1 dan ch <- 2 untuk menghantar dua elemen ke saluran. Akhir sekali, kami menggunakan <-ch untuk membaca dua elemen daripada saluran dua kali.

Perlu diingatkan bahawa jika kita cuba menghantar elemen ke saluran penimbal yang sudah penuh, operasi hantar akan menyekat sehingga terdapat kedudukan bebas dalam saluran. Begitu juga, jika kita cuba membaca elemen daripada saluran buffer kosong, operasi baca juga akan menyekat sehingga terdapat elemen dalam saluran.

  1. Tutup saluran

Apabila menggunakan saluran tak segerak, kita mesti memberi perhatian kepada beberapa butiran. Sebagai contoh, apakah yang berlaku apabila kita membaca data daripada saluran tertutup?

Apabila kami cuba membaca data daripada saluran tertutup, operasi baca tidak lagi akan menyekat, tetapi akan segera mengembalikan nilai sifar. Sebagai contoh, dalam contoh berikut kita dapat melihat bahawa apabila kita membaca elemen dari saluran tertutup, nilai sifar jenis akan dikembalikan:

package main

import "fmt"

func main() {
    ch := make(chan int)
    close(ch)     // 关闭信道
    x, ok := <-ch // 读取信道
    fmt.Println(x, ok) // 输出:0 false
}

Perlu diingatkan bahawa kita perlu memastikan bahawa terdapat Hanya tutup saluran apabila coroutine menggunakannya. Jika hanya satu coroutine yang menggunakan saluran, maka kami tidak perlu menutup saluran secara manual, kerana ini boleh menyebabkan coroutine lain panik apabila cuba menghantar data ke saluran ini.

  1. Mekanisme tamat masa saluran

Dalam sesetengah kes, kami mungkin menghadapi masalah tamat masa semasa menunggu data daripada saluran. Contohnya, apabila kami membaca data daripada sambungan rangkaian, jika masa ketibaan data melebihi masa menunggu yang kami tetapkan, maka kami perlu menutup sambungan supaya coroutine lain boleh menggunakan sumber ini.

Dalam pemprosesan saluran tak segerak, kita boleh menggunakan pernyataan select untuk menyesuaikan mekanisme tamat masa. Berikut ialah contoh menggunakan pernyataan select untuk melaksanakan mekanisme tamat masa saluran:

package main

import (
    "fmt"
    "time"
)

func main() {
    ch := make(chan int)
    go func() {
        time.Sleep(5 * time.Second)
        ch <- 1
    }()
    select {
    case x := <-ch:
        fmt.Println(x)
    case <-time.After(3 * time.Second):
        fmt.Println("timeout!")
    }
}

Dalam contoh di atas, kami menggunakan fungsi time.After() untuk mengembalikan contoh jenis time.Timer untuk menunggu tamat masa. Jika saluran menerima data sebelum tamat masa, kami boleh mendapatkan data daripada pernyataan x := <-ch. Jika tidak, apabila tamat masa berlaku, pernyataan <-time.After(3 * time.Second) akan dilaksanakan serta-merta dan maklumat berkaitan tamat masa akan dikeluarkan.

Perlu diingatkan bahawa apabila menggunakan mekanisme tamat masa saluran, kita juga harus memberi perhatian kepada saluran mana yang ditutup untuk mengelakkan panik sementara menunggu saluran menerima data.

  1. penyataan pilih

select pernyataan ialah struktur bahasa yang sangat penting dalam bahasa Go, yang membolehkan kami menunggu beberapa operasi komunikasi pada masa yang sama. Apabila berbilang operasi komunikasi sedia, pernyataan select akan memilih pernyataan secara rawak untuk dilaksanakan.

Berikut ialah contoh menggunakan penyata select, di mana kami menunggu untuk kedua-dua saluran menghantar dan menerima operasi:

package main

import (
    "fmt"
)

func main() {
    ch1 := make(chan int)
    ch2 := make(chan int)
    go func() {
        ch1 <- 1
    }()
    select {
    case x := <-ch1:
        fmt.Println(x)
    case ch2 <- 2:
        fmt.Println("send 2")
    }
}

Dalam contoh di atas, kami menggunakan pernyataan go untuk menunggu untuk yang baharu Laksanakan pernyataan ch1 <- 1 dalam coroutine. Kemudian, kami menggunakan pernyataan select untuk menunggu saluran ch1 dan ch2 secara serentak. Jika terdapat elemen dalam ch1, kita boleh mengeluarkannya daripada pernyataan x:= <-ch1 dan mencetaknya. Sebaliknya, jika ch2 boleh menghantar elemen, kemudian laksanakan ch2 <- 2 dan cetak output.

Perlu diingatkan bahawa apabila menggunakan penyata select, kita tidak perlu melakukan operasi terima dan hantar pada semua saluran. Sebagai contoh, dalam contoh di atas kami hanya melakukan operasi penerimaan pada ch1 dan hanya melakukan operasi penghantaran pada ch2.

Ringkasan:

Dalam bahasa Go, pemprosesan saluran tak segerak ialah teknologi yang sangat penting. Apabila pengaturcaraan secara tak segerak, kita boleh menggunakan saluran penimbal, saluran tertutup, saluran tamat masa, dsb. untuk menggunakan sepenuhnya ciri komunikasi saluran yang cekap. Pada masa yang sama, kita juga harus memberi perhatian kepada beberapa teknik, seperti hanya menutup saluran yang sedang digunakan oleh berbilang coroutine, menggunakan pernyataan select, dsb. Sudah tentu, hanya beberapa teknik biasa yang diperkenalkan di sini Teknik pemprosesan saluran tak segerak perlu dipelajari dan diterokai oleh kami sendiri.

Atas ialah kandungan terperinci Teknik pemprosesan saluran tak segerak dalam bahasa Go. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn