- vừa được xem lúc

Golang Channel giao tiếp giữa các goroutine.

0 0 26

Người đăng: Open Dev

Theo Viblo Asia

Vấn Đề

Nói đến golang là nói đến Concurrency, nhằm mục đích tăng hiệu năng performance, thì việc trong 1 api hoặc trong 1 logic có rất nhiều goroutine là chuyện thường xuyên xảy ra. Thì bài viết này mình sẽ nói đến việc giao tiếp giữa 2 goroutine.


Giải Quyết

Để hỗ trợ việc giao tiếp giữa các goroutine thì trong golang người ta thường dùng channel nếu các bạn chưa biết channel là gì và cách dùng nó thì đọc bài giới thiệu này nhé.

Code Mẫu

Không sử dụng channel để giao tiếp giữa 2 goroutine:

package main import ( "fmt" "time"
) func main() { fmt.Println("main") startTime := time.Now() process1() process2() endTime := time.Since(startTime).Milliseconds() fmt.Println("tong process 1:", endTime) } func process1() { startTime := time.Now() // ví dụ process 1 này có 3 logic, và 1 logic sẽ tốn 100 millisecond // 1. là get thông tin user từ database fmt.Println("process1: get info user") // sau này có thể thay login ở dòng này time.Sleep(time.Millisecond * 100) // 2. sau khi có thông tin user thì lấy history các bình luận thông qua userID fmt.Println("process1: get bình luận của user") time.Sleep(time.Millisecond * 100) // 3. Process này là xem các bình luận nào thuộc bài viết đã được xoá thì cũng xoá bình luận tương ứng đó. fmt.Println("process1: xoá bình luận của bình viết không tồn tại") time.Sleep(time.Millisecond * 100) // => tổn cộng sau khi handle xong thì bạn tốn khoảng hơn 300 millisecond endTime := time.Since(startTime).Milliseconds() fmt.Println("time process 1:", endTime)
} func process2() { startTime := time.Now() // ví dụ process 1 này có 3 logic, và 1 logic sẽ tốn 100 millisecond // 1. Get thông tin tất cả các bài viết fmt.Println("process2: get thông tin bài viết") // sau này có thể thay login ở dòng này time.Sleep(time.Millisecond * 100) // 2. Thực hiện fillter các bài viết fmt.Println("process2: thực hiện fillter trên code") time.Sleep(time.Millisecond * 100) // 3. Process này là sort data. fmt.Println("process2: xử lý sort data để trả về tăng dần") time.Sleep(time.Millisecond * 100) // => tổn cộng sau khi handle xong thì bạn tốn khoảng hơn 300 millisecond endTime := time.Since(startTime).Milliseconds() fmt.Println("time process 1:", endTime)
}

Kết quả:

main

process1: get info user

process1: get bình luận của user

process1: xoá bình luận của bình viết không tồn tại

time process 1: 303

process2: get thông tin bài viết

process2: thực hiện fillter trên code

process2: xử lý sort data để trả về tăng dần

time process 1: 303

tong process 1: 607

=> ở ví dụ trên mình không sài goroutine thì tổng thời gian thực hiện là khoản 605 millisecond

RUN


Tới đây chắc nhiều bạn thắc mắc đó là tại sao không sài goroutine để thực hiện đồng thời cả 2 cùng một lúc. Thì mình sẽ giải thích rằng là bạn đã đúng rồi trong trường hợp 2 process này không phụ thuộc lẫn nhau. Không phụ thuộc là data của 2 process này độc lập.

Còn ở đây mình muốn là phụ thuộc lẫn nhau để xử dụng channel, trong process2 đến phần số 2 muốn thực hiện được cần phải có userID thì bạn buộc phải waiting process1 thực hiện xong việc lấy userID thì process2 mới có để thực hiện.

package main import ( "fmt" "sync" "time"
) func main() { fmt.Println("main") startTime := time.Now() wg := sync.WaitGroup{} ch := make(chan string) wg.Add(2) go process1(&wg, ch) go process2(&wg, ch) wg.Wait() endTime := time.Since(startTime).Milliseconds() fmt.Println("tong process:", endTime)
} func process1(wg *sync.WaitGroup, ch chan string) { defer wg.Done() startTime := time.Now() // ví dụ process 1 này có 3 logic, và 1 logic sẽ tốn 100 millisecond // 1. là get thông tin user từ database fmt.Println("process1: get info user") // sau này có thể thay login ở dòng này time.Sleep(time.Millisecond * 100) // 2. sau khi có thông tin user thì lấy history các bình luận thông qua userID fmt.Println("process1: get bình luận của user") time.Sleep(time.Millisecond * 100) ch <- "123123" // 3. Process này là xem các bình luận nào thuộc bài viết đã được xoá thì cũng xoá bình luận tương ứng đó. fmt.Println("process1: xoá bình luận của bình viết không tồn tại") time.Sleep(time.Millisecond * 100) // => tổn cộng sau khi handle xong thì bạn tốn khoảng hơn 300 millisecond endTime := time.Since(startTime).Milliseconds() fmt.Println("time process 1:", endTime)
} func process2(wg *sync.WaitGroup, ch chan string) { defer wg.Done() startTime := time.Now() // ví dụ process 2 tương tự như process 1 cũng có 3 logic, và 1 logic sẽ tốn 100 millisecond // 1. là get thông tin user từ database fmt.Println("process2: get info user") // sau này có thể thay login ở dòng này time.Sleep(time.Millisecond * 100) fmt.Println("process2: blocking process") userID := <-ch fmt.Println("process2:userID", userID) // 2. sau khi có thông tin user thì lấy history các bình luận thông qua userID fmt.Println("process2: get bình luận của user") time.Sleep(time.Millisecond * 100) // 3. Process này là xem các bình luận nào thuộc bài viết đã được xoá thì cũng xoá bình luận tương ứng đó. fmt.Println("process2: xoá bình luận của bình viết không tồn tại") time.Sleep(time.Millisecond * 100) // => tổn cộng sau khi handle xong thì bạn tốn khoảng hơn 300 millisecond endTime := time.Since(startTime).Milliseconds() fmt.Println("time process 1:", endTime)
}

Kết quả:

main

process2: get info user

process1: get info user

process2: blocking process

process1: get bình luận của user

process1: xoá bình luận của bình viết không tồn tại

process2:userID 123123

process2: get bình luận của user

process2: xoá bình luận của bình viết không tồn tại

time process 1: 303

time process 1: 404

tong process: 404

=> với việc sử dụng goroutine kết hợp channel thì tổng thời gian có thể giảm đi khá nhiều, ở đây là khoảng 404 millisecond

RUN

Bình luận

Bài viết tương tự

- vừa được xem lúc

gRPC - Nó là gì và có nên sử dụng hay không?

Nhân một ngày rảnh rỗi, mình ngồi đọc lại RPC cũng như gRPC viết lại để nhớ lâu hơn. Vấn đề là gì và tại sao cần nó .

0 0 112

- vừa được xem lúc

Embedded Template in Go

Getting Start. Part of developing a web application usually revolves around working with HTML as user interface.

0 0 40

- vừa được xem lúc

Tạo Resful API đơn giản với Echo framework và MySQL

1. Giới thiệu.

0 0 44

- vừa được xem lúc

Sử dụng goquery trong golang để crawler thông tin các website Việt Nam bị deface trên mirror-h.org

. Trong bài viết này, mình sẽ cùng mọi người khám phá một package thu thập dữ liệu có tên là goquery của golang. Mục tiêu chính của chương trình crawler này sẽ là lấy thông tin các website Việt Nam bị deface (là tấn công, phá hoại website, làm thay đổi giao diện hiển thị của một trang web, khi người

0 0 218

- vừa được xem lúc

Tạo ứng dụng craw dữ liệu bing với Golang, Mysql driver

Chào mọi người . Lâu lâu ta lại gặp nhau 1 lần, để tiếp tục series chia sẻ kiến thức về tech, hôm nay mình sẽ tìm hiểu và chia sẻ về 1 ngôn ngữ đang khá hot trong cộng đồng IT đó là Golang.

0 0 59

- vừa được xem lúc

Golang: Rest api and routing using MUX

Routing with MUX. Let's create a simple CRUD api for a blog site. # All . GET articles/ .

0 0 39