Lấy nguồn từ https://gobyexample.com/channels thì channel là:

Các pipes(đường ống) kết nối các concurrent goroutines, hiểu là để giao tiếp các goroutines với nhau thông qua cách: Gửi 1 giá trị vào channel rồi sau đó lấy giá trị đó từ channel rồi xử lý tiếp.


1.Channels
2.Buffered Channels
3.select
4.close channels


Channel

  • Tạo mới 1 channel sử dụng:
    •  make(chan val-type)
  • Gửi 1 giá trị vào channel sử dụng:
    • channel <- syntax
  • Để nhận giá trị của 1 channel sử dụng:
    • syntax <- channel

Ví dụ sử dụng channels:

func main() {
		// create channel/ Tạo mới 1 channel
			ch := make(chan string)

	 	go func() {
	 	// Send a value/ gửi 1 giá trị vào channel
			ch <- "name : chuyenmucit.code.blog"
                        fmt.Println("done")
		}()
		// receives a value/ nhận giá trị từ channel
			nameUser :=  <- ch
			fmt.Println(nameUser)

}

kết quả nhận được khi in giá trị nameUser nhận từ channel `ch`:

channel basic

Khi gửi hoặc nhận giá trị của channel(unbuffered channel) thì chương trình bị block cho tới khi hoàn thành việc gửi hoặc nhận giá trị. Do channel cứ đợi

Cụ thể khi không có goroutines nào gửi giá trị vào channle thì chương trình sẽ log lỗi deadlock
Và khi truyền vào channle mà không lấy giá trị của channel đó thì những công việc đằng sau việc gửi value vào cahnnel sẽ không được thực thi do bị block tại lúc gửi giá trị vào channel.
Ví dụ như sau.

Vẫn đoạn code trên, bạn bỏ đi việc lấy value từ channel bằng việc xóa đi đoạn code:

nameUser :=  <- ch
fmt.Println(nameUser)

Do chúng ta không lấy gái chị channle lên channel cứ đợi để gửi giá trị đó nên goroutines bị blog từ đoạn

ch <- "name : chuyenmucit.code.blog"

Kết quả là không in ra được gì 😀
Nếu bạn đọc dữ liệu từ một channel nhưng channel đó không có giá trị với nó, nó sẽ chặn (block) goroutine hiện tại nhưng ko chặn các goroutine khác cho đến khi có goroutine nào đó ghi dữ liệu lên nó. Tương tự nếu bạn ghi dữ liệu vào 1 channel, nó sẽ chặn goroutine hiện tại và không chặn các goroutine khác cho đến khi có goroutine nào đó đọc dữ liệu từ nó.

Buffered Channels

Cách làm việc BC:

Chỉ khác với unbuffered channel:
1. Không bị block khi gửi hay nhận giá trị từ channle
2. Sau khi sử dụng close(channel) thì những giá trị channle được gọi sau
close sẽ trả về zero value với:
The zero value is:

  • 0 for numeric types,
  • false for the boolean type, and
  • "" (the empty string) for strings.

Select

Theo 1 nguồn nào đó:
Trong ngôn ngữ Go, câu lệnh select giống như câu lệnh Switch, nhưng trong câu lệnh select, câu lệnh case liên quan đến việc trao đổi thông tin ví dụ như các hoạt động nhận và gửi trên channel. Thông thường mỗi câu lệnh case sẽ được đọc thử từ channel. Khi một case bất kỳ sẵn sàng (channel được đọc), thì câu lệnh kết hợp với case đó được chạy. Nếu nhiều case sẵn sàng, nó sẽ lựa chọn ngẫu nhiên một. Bạn có thể có case mặc định được chạy nếu không có case nào sẵn sàng.

Ví dụ câu lệnh select:

package main

import (
	"fmt"
)

func main() {
			// select
	queue := make(chan int)
	done := make(chan bool)

	go func() {
		for i:= 0;i< 10;i++ {
			queue <- i
		}
		done <- true
	}()
	for {
		select {
		case v := <-queue:
			fmt.Println(v)
		case <- done:
 			fmt.Println("done")
			return
		}
	}

chú ý rằng:
Câu lệnh select bị chặn khi không có một câu lệnh case nào ở trạng thái sẵn sàng và câu lệnh select không chứa bất kỳ case mặc định nào, thì câu lệnh select sẽ bị chặn cho tới khi ít nhất có một case hoặc việc trao đổi thông tin được tiến hành

Close

  1. Không thể gửi giá trị vào channel đã close.

ok, code4fun !