5 lý do bạn nên học Golang ngay và luôn

nên học golang

Có nên học Golang không?

“Go will be the server language of the future.” — Tobias Lütke, Shopify  

Tạm dịch: Go sẽ là ngôn ngữ server của tương lai.

Trong những năm gần đây là sự trỗi dậy của một ngôn ngữ lập trình mới. Go hay còn gọi là Golang. Không có gì thích thú hơn việc một ngôn ngữ mới ra đời đối với lập trình viên phải không?. Vì vậy mình đã bắt đầu học Golang từ 4-5 tháng trước và bây giờ mình sẽ nói cho các bạn 5 lý do tại sao chúng ta nên học ngôn ngữ mới này.

Trong bài viết này mình sẽ giải thích về giai đoạn hiện tại của phần mềm/phần cứng máy tính. Và lý do tại sao chúng ta cần một ngôn ngữ mới như Go. Bởi vì nếu không xảy ra vấn đề gì thì chúng ta cũng chả cần đến một giải pháp mới nào phải không?

Hạn chế của phần cứng

Nhân xử lý Pentium 4 đầu tiên với xung nhịp 3.0GHz clock đã được giới thiệu bởi Intel từ 2004. Thời điểm hiện tại Macbook Pro 2016 của mình có xung nhịp 2.9GHz. Vì vậy, gần một thập kỷ đã không có thay đổi gì nhiều trong sức mạnh của vi xử lý. Chúng ta có thể xem qua biểu đồ so sánh sự gia tăng của khả năng xử lý theo thời gian dưới đây:

nên học golang

Từ biểu đồ trên các bạn có thể thấy hiệu suất của single-thread và tần số của vi xử lý vẫn duy trì ổn định trong suốt một thập kỷ. Nếu các bạn nghĩ rằng, thêm nhiều linh kiện bán dẫn là một giải pháp thì các bạn đã nhầm to rồi. Bởi vì ở quy mô nhỏ hơn một số tính chất lượng tử bắt đầu xuất hiện (như tunneling). Và sẽ tốn nhiều chi phí hơn để đặt nhiều linh kiện bán dẫn. Càng thêm nhiều linh kiện bán dẫn thì ví của bạn sẽ càng xẹp lép.

Vì thế, giải pháp cho vấn đề trên là:

  • Các nhà sản xuất ngày càng thêm nhiều nhân vào vi xử lý. Vì thế ngày nay chúng ta có các vi xử lý dual-corequad-core và octa-core.
  • Hyper-threading cũng đã được giới thiệu
  • Thêm nhiều cache vào vi xử lý để tăng thêm hiệu suất

Nhưng các giải pháp trên cũng đều có những hạn chế. Chúng ta không thể thêm quá nhiều cache vào vi xử lý để tăng hiệu suất bởi cache cũng có những giới hạn vật lý: cache càng phình to thì càng chậm. Thêm quá nhiều nhân vào vi xử lý cũng có cái giá của nó. Ngoài ra, cũng không thể mở rộng vô giới hạn được.

Vì thế, nếu chúng ta không thể dựa vào sự cải tiên của phần cứng thì cách duy nhất là cải thiện phần mềm để tăng hiệu suất. Nhưng đáng tiếc thay, những ngôn ngữ hiện đại thời nay không thực sự hiệu quả.

“Modern processors are a like nitro fueled funny cars, they excel at the quarter mile. Unfortunately modern programming languages are like Monte Carlo, they are full of twists and turns.” — David Ungar  

Tạm dịch: “Những bộ vi xử lý hiện đại cũng giống như những chiếc xe chạy bằng nitro. Chúng thật sự xuất sắc ở cuộc đua thể thao chặng ngắn. Tuy nhiên những ngôn ngữ hiện đại như Monte Carlo. Chúng lại giống như những con đường đầy ngã rẽ và gấp khúc”

Go có goroutines !!

Như chúng ta đã thảo luận ở trên, các nhà sản xuất phần cứng đang thêm vào nhiều và nhiều nhân hơn nữa vào vi xử lý để tăng hiệu suất. Tất cả trung tâm dữ liệu đều chạy trên những vi xử lý đó và chúng ta nên mong đợi số lượng nhân sẽ tăng thêm trong thời gian tới. Thêm vào đó, ngày nay các ứng dụng sử dụng nhiều micro-services để duy trì kết nối cơ sở dữ liệu, hàng đợi tin nhắn và duy trì bộ nhớ cache. Vì vậy, phần mềm chúng ta phát triển và các ngôn ngữ lập trình nên hỗ trợ các tác vụ đồng thời dễ dàng và chúng có thể mở rộng được với số lượng nhân tăng lên.

Nhưng hầu hết các ngôn ngữ lập trình hiện đại (như Java, Python, …) là từ môi trường single threaded của thập niên 90. Hầu hết các ngôn ngữ lập trình hỗ trợ đa luồng. Nhưng vấn đề thực sự đến từ các tác vụ thực hiện đồng thời, threading-locking, race conditions và deadlock. Những điều đó làm cho việc tạo một ứng dụng đa luồng trên các ngôn ngữ đó trở nên khó khăn.

Ví dụ như tạo một thread mới trong Java khá là ngốn bộ nhớ. Vì mỗi thread ngốn khoảng 1MB bộ nhớ heap và cuối cùng nếu bạn bắt đầu tạo hàng ngàn thread. Chúng sẽ gây áp lực rất lớn lên heap và sẽ bị sập do tràn bộ nhớ. Ngoài ra, nếu bạn muốn giao tiếp giữa hai hoặc nhiều threads, việc đó cũng rất khó khăn.

Mặt khác, Go được phát hành vào năm 2009 khi bộ xử lý nhiều nhân đã có sẵn. Go có goroutines thay vì threads. Chúng chỉ ngốn ~ gần 2KB bộ nhớ từ heap. Vì vậy, bạn có thể tạo hàng triệu goroutines bất cứ lúc nào.

goroutine

Những lợi ích khác như:

  • Goroutines có ngăn xếp phân đoạn có thể mở rộng. Điều đó có nghĩa là chúng sẽ chỉ sử dụng nhiều bộ nhớ hơn khi cần thiết.
  • Goroutines có thời gian khởi động nhanh hơn các threads.
  • Goroutines đi kèm với các nguyên lý tích hợp để giao tiếp an toàn giữa chúng (các kênh).
  • Goroutines cho phép bạn tránh phải dùng đến mutex locking khi chia sẻ cấu trúc dữ liệu.
  • Ngoài ra, các Goroutines và các luồng hệ điều hành không có ánh xạ 1: 1. Một goroutine có thể chạy trên nhiều luồng. Goroutines được ghép thành một số lượng nhỏ các luồng của hệ điều hành.

Tất cả những điểm trên cho thấy Go vô cùng mạnh mẽ trong việc xử lý các tác vụ đồng thời không thua kém Java, C hay C++. Trong khi vẫn giữ được mã nguồn thực thi đồng thời sạch đẹp như Erlang.

concurrency golang

Chạy trực tiếp trên nền tảng phần cứng

Một trong những ưu điểm đáng kể nhất của C, C++ so với những ngôn nhữ cấp cao hiện đại khác như Java/Python là hiệu suất. Bởi vì C/C++ được biên dịch và không cần trình thông dịch.

Vi xử lý hiểu được mã nhị phân. Nhìn chung, khi bạn xây dựng một ứng dụng sử dụng Java hay các ngôn ngữ JVM-based. Khi biên dịch dự án, nó sẽ biên dịch mã nguồn thành byte-code cho JVM hoặc các máy ảo khác chạy trên nền hệ điều hành. Trong khi thực thi, máy ảo sẽ thông dịch những mã bytecodes đó sang mã nhị phân để vi xử lý có thể hiểu được.

golang flow 1

Mặc khác, C/C++ không thực thi trên máy ảo vì thế đã giảm đi được một bước trong quá trình thực thi và gia tăng hiệu suất đáng kể. Nó biên dịch trực tiếp mã nguồn thành mã nhị phân.

golang flow 2

Nhưng việc giải phóng và cấp phát biến cho những ngôn ngữ như C/C++ thật sự là mệt mỏi. Trong khi hầu hết những ngôn ngữ lập trình xử lý việc cấp phát đối tượng và giải phóng sử dụng thuật toán Garbage Collector hoặc Reference Counting.

Go mang lại sự hài hòa tốt nhất cho cả 2 thế giới. Cũng giống như ngôn ngữ bậc thấp như C/C++, Go là ngôn ngữ biên dịch. Điều đó có nghĩa là hiệu suất ngang với ngôn ngữ bậc thấp. Nó cũng sử dụng garbage collection để cấp phát và giải phóng đối tượng. Vì vậy, không còn cần đến malloc() hay free() nữa. Quá ngầu đúng không?

Mã nguồn được viết bằng Go rất dễ bảo trì

Go không có cú pháp lập trình điên rồ như các ngôn ngữ khác có. Nó có cú pháp rất gọn gàng và sạch sẽ.

Các nhà thiết kế của Go tại google đã nghĩ đến điều này khi họ tạo ra ngôn ngữ. Vì google có code-base rất lớn và hàng ngàn nhà phát triển đang làm việc trên cùng một code-base đó. Nên mã nguồn phải dễ hiểu đối với các nhà phát triển khác và một đoạn mã sẽ ít ảnh hưởng nhất tới một đoạn mã khác. Điều đó sẽ làm cho mã nguồn dễ dàng duy trì và dễ sửa đổi.

Go cố tình bỏ đi nhiều tính năng của các ngôn ngữ OOP (hướng đối tượng) hiện đại.

  • Không có Class. Mỗi thứ chỉ được chia thành các packages. Go chỉ có structs thay vì các classes.
  • Không hỗ trợ thừa kế (inheritance). Điều đó sẽ làm cho mã nguồn dễ dàng sửa đổi. Trong các ngôn ngữ khác như Java / Python, nếu lớp ABC kế thừa lớp XYZ và bạn thực hiện một số thay đổi trong lớp XYZ. Điều đó có thể tạo ra một số tác dụng phụ trong các lớp khác kế thừa XYZ. Bằng cách loại bỏ tính kế thừa, Go cũng giúp bạn dễ hiểu mã nguồn hơn (vì không có super class nào khi đọc mã nguồn).
  • Không có constructors.
  • Không có annotations.
  • Không có generic.
  • Không có exceptions.

Những thay đổi ở trên làm cho Go rất khác biệt với các ngôn ngữ khác và nó làm cho lập trình trong Go cũng khác với các ngôn ngữ khác. Bạn có thể không thích một số điểm ở trên… Nhưng về mặt tích cực, nó sẽ làm cho mã nguồn của bạn sạch sẽ hơn và thêm rõ ràng hơn và là một rtong những nguyên nhân mà bạn nên học Golang.

language comparison

Biểu đồ trên chỉ ra rằng Go cũng hiệu quả như C/C++. Trong khi vẫn giữ được cú pháp lập trình đơn giản như Ruby, Python và một số ngôn ngữ khác. Đó là mối quan hệ win-win cho cả loài người và vi xử lý.

Không giống như những ngôn ngữ khác như Swift, cú pháp của Go rất ổn định. Nó vẫn duy trì và không thay đổi kể từ khi release phiên bản 1.0 vào năm 2012. Điều đó giúp cho nó có thể tương thích ngược.

Go được chống lưng bởi google

Mình biết đây không phải là một lợi thế kỹ thuật trực tiếp. Nhưng, Go được thiết kế và hỗ trợ bởi Google. Google có một trong những cơ sở hạ tầng đám mây lớn nhất trên thế giới. Go được thiết kế bởi Google để giải quyết các vấn đề của họ về hỗ trợ khả năng mở rộng và hiệu quả. Đó là những vấn đề tương tự bạn sẽ gặp phải trong khi tạo máy chủ của riêng bạn.

Thêm vào đó Go cũng được sử dụng bởi một số công ty lớn như Adobe, BBC, IBM, Intel và thậm chí là Medium. (Nguồn: https://github.com/golang/go/wiki/GoUsers)

Tổng kết

  • Mặc dù Go rất khác với các ngôn ngữ hướng đối tượng khác, nhưng nó vẫn là một con quái thú. Go cung cấp cho bạn hiệu suất cao như C/C++, xử lý đồng thời siêu hiệu quả như Java và dễ code như Python / Perl.
  • Nếu bạn không có kế hoạch học Go, mình vẫn sẽ nói giới hạn phần cứng sẽ gây áp lực cho chúng ta và các nhà phát triển phần mềm để viết mã nguồn siêu hiệu quả. Nhà phát triển cần hiểu rõ về phần cứng và tối ưu hóa chương trình của họ cho phù hợp. Phần mềm được tối ưu hóa có thể chạy trên phần cứng rẻ hơn và chậm hơn (như thiết bị IOT) và tác động tổng thể tốt hơn đến trải nghiệm người dùng cuối.
  • Các bạn có ý định bắt đầu học Golang thì dạo qua bài đăng này nhé: https://huynhphuchuy.com/golang/nhung-dinh-nghia-can-ban-trong-golang
45 Bình luận
Write a comment