Với syntax có phần giống C++ nhưng lại rất đơn giản, từ đó nó đã được phát triển lên rất nhiều và được sử dụng bởi nhiều lập trình viên trên toàn thế giới để tạo nên những ứng dụng, hệ t
Trang 1LẬP TRÌNH NÂNG CAO (CO2039)
TIỂU LUẬN TÌM HIỂU VỀ GOLANG
GVHD: Trương Tuấn Anh
SV: Lương Hồng Tiến Đạt – 2012924
Tp Hồ Chí Minh, Tháng 5/2022
Trang 2Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học & Kỹ Thuật Máy Tính
Mục lục
2.1 Một số đặc điểm của Go
2.2 Cách sử dụng và lập trình với ngôn ngữ Golang
2.2.9 Hàm
2.2.11 Map
2.3 Điểm mạnh, điểm yếu của Golang
Tài liệu
Trang 31 LỜI MỞ ĐẦU
Go hay Golang là một ngôn ngữ nguồn mở, đa nền tảng, và là ngôn ngữ được phát triển tại Google bởi Robert Griesemer, Rob Pike, và Ken Thompson vào năm 2007 Với syntax có phần giống C++ nhưng lại rất đơn giản, từ đó nó đã được phát triển lên rất nhiều và được sử dụng bởi nhiều lập trình viên trên toàn thế giới để tạo nên những ứng dụng, hệ thống với hiệu quả rất cao
Hình 1: Logo của ngôn ngữ Golang Golang được sử dụng cho rất nhiều mục dích khác nhau, ta có thể kể đến những lĩnh vực mà sử dụng nó rất hiệu quả như:
• Sử dụng cho việc phát triển website ở phía Server (Web development)
• Sử dụng cho việc phát triển các chương trình Network-based tức là những chương trình chạy trên những mạng lưới và giao tiếp với nhiều máy tính khác nhau
• Sử dụng cho việc phát triền những ứng dụng Enterprise đa nền tảng
• Phát triển Cloud native, tức là tiếp cận, xây dựng các dự án dựa trên các lợi thể của mô hình điện toán đám mây
Và trong bài tiểu luận này, ta sẽ tìm hiểu về ngôn ngữ Golang, cách sử dụng tiếp cận nó cũng như đưa ra những lợi thế và yếu điểm của ngôn ngữ đang trở nên rất phổ biến và được ưa chuộng này
2.1 Một số đặc điểm của Go
Ta có thể kể đến những đặc điểm nổi bật của Golang như:
• Go là ngôn ngữ lập trình biên soạn (compiled language) Phần mềm viết bởi Go cần được biên soạn sử dụng Go compile trước khi có thể chạy được
với mã của bạn, điều này sẽ giúp bạn hiểu được phạm vi của mã bằng các kiểm tra riêng từng phần
• Golang hỗ trợ xử lý đa luồng multi-threading
• Go là một ngôn ngữ lập trình kiểu tĩnh (hay static type), các biến hoặc dữ liệu trong Golang sẽ không thay đổi trong suốt chương trình
• Với nền tảng độc lập, Golang cũng giống như ngôn ngữ Java, hỗ trợ tính năng độc lập của nền tảng, mã được biên dịch và chuyển đổi thành dạng nhị phân càng nhỏ càng tốt Mã của Golang có thể được biên dịch trong bất kỳ nền tảng nào hoặc bất kỳ máy chủ và ứng dụng nào bạn đang làm việc
2.2 Cách sử dụng và lập trình với ngôn ngữ Golang
2.2.1 Cài đặt và sử dụng Golang
Như những ngôn ngữ lập trình khác, ta sẽ cần text editor để viết code và compiler để biên dịch Có rất nhiều lựa chọn cho các lập trình viên
Để cài đặt ta có thể truy cập vào đường link sau: https://golang.org/dl/
Sau đó, nếu bạn dùng VScode, bạn có thể cài đặt extension của Golang và chạy các chương trình
sử dụng Golang
Trang 4Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học & Kỹ Thuật Máy Tính
2.2.2 Syntax cơ bản của Go
Trước tiên để nói về những quy tắc cơ bản về syntax của Go, thì ta sẽ xem xét về cấu trúc của một
file code Go sẽ gồm những phần nào Ta xét một ví dụ là một nội dung của một file Go đơn giản như
sau:
1 package main
2 import ( " fmt " )
3
4 func main () {
5 fmt Println ( " Advanced P r o g r a m m i n g " )
6 }
Listing 1: Ví dụ về file code Go đơn giản
Và từ đây ta có thể chia cấu trúc của một file mã Go cơ bản sẽ gồm những phần như sau:
• Khai báo package (Ta dùng từ khóa package như dòng 1 của ví dụ trên, chương trình
thuộc về package main)
• Import những package cần thiết khác (Ví dụ như package fmt được import vào ở dòng 2
ở ví dụ trên)
’{}’)
• Các câu lệnh, biểu thức: Những câu lệnh của Go sẽ được ngăn cách nhau bằng cách
xuống dòng (Phím Enter) hoặc bởi dấu ’;’
2.2.3 Kiểu dữ liệu và khai báo biến
Tương tự những ngôn ngữ khác, Go cũng cung cấp những kiểu dữ liệu như sau:
• int: Kiểu dữ liệu lưu trữ số nguyên
• float32 : Kiểu dữ liệu lưu trữ số thực 32 bits
• string: Kiểu dữ liệu lưu trữ chuỗi ký tự, được ngăn cách bởi dấu ngoặc kép
• bool: Kiểu dữ liệu lưu trữ giá trị logic: true hoặc false
Ngoài ra còn những kiểu dữ liệu khác như uint, byte, rune,
Và tiếp theo, để có thể khai báo biến ta có thể sử dụng một trong hai cách sau:
• Sử dụng từ khóa var theo syntax: var <variablename> <type> = <value>
• Sử dụng ":=" theo sau bởi giá trị của biến, từ đó compiler sẽ infer type của biến được
gán, do vậy khi sử dụng cách này, bắt buộc ta phải đưa ra khá trị được gán
Ta có thể lấy đoạn chương trình dưới đây là ví dụ:
1 package main
2 import " fmt "
3
5 var name string = " Luong Dat " // Type is
10 fmt Println ( name )
11 fmt Println ( address )
12 fmt Println (a , b , c )
13 fmt Println ( num )
14 fmt Println (c , d )
15 }
Listing 2: Ví dụ về khai báo biến
Trang 5Ở ví dụ trên đã đưa ra những ví dụ về cách khai báo sử dụng từ khóa var cho một biến, khai báo
không cần value hay khai báo một lúc nhiều biến cũng như khai báo sử dụng inferring một biến và
nhiều biến Ta thu được kết quả như sau (với những biến không có initial value sẽ được khởi tạo giá
trị mặc định, ví dụ như string mặc định sẽ là "", int mặc định sẽ là 0, bool mặc định là false):
1 Luong Dat
2
3 8117
4 811
5 7 World !
Ngoài ra, Go cũng hỗ trợ việc khai báo hằng bằng từ khóa const, những biến hằng là những biến
read-only và không thể thay đổi giá trị, ta có thể khai báo như ví dụ sau:
1 package main
2 import ( " fmt " )
3
4 const PI = 3.14
5
6 func main () {
7 fmt Println ( PI )
8 }
Listing 3: Ví dụ về hằng
Ta nhận được kết quả:
1 3.14
2.2.4 Xử lý output ra màn hình
Để đưa kết quả ra console, ta có thể sử dụng ba hàm được cung cấp trong package fmt như sau:
• Print(): Để in các biến truyền vào trong một hàng, nếu muốn xuống hàng có thể sử dụng
thêm " n"
• Println(): Tương tự Print() nhưng hàm sẽ in các biến cách nhau bởi một space trống và
xuống hàng khi in hết
• Printf(): In theo định dạng tùy chỉnh dựa vào thêm vào formatting verbs như:
- %v: in giá trị của biến
- %T : in kiểu dữ liệu của biến
- %b: in theo dạng binary
- Ngoài ra còn có nhiều formatting verbs khác như %o, %#v,
1 package main
2 import ( " fmt " )
3
6
7 fmt Print (i , j , "\n" )
8 fmt Println (i , j )
9 fmt Printf ( "In ra i = %v, co type la %T " , i , i )
10 }
Listing 4: Ví dụ về lệnh in
Ta nhận được kết quả:
1 H e l l o W o r l d
2 Hello World
3 In ra i = Hello , co type la string
Trang 6Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học & Kỹ Thuật Máy Tính
2.2.5 Array
Với Go, để có thể sử dụng mãng, ta cũng cần khai báo mãng theo hai cách như sau:
var <array_name> = [<length>]<datatype><values>
<array_name> := [<length>]<datatype><values>
Nếu length không được nêu rõ thì length sẽ được infer từ values
Ta có thể xem ví dụ sau:
1 package main
2 import ( " fmt " )
3
7 fmt Println ( a )
8 fmt Println ( b )
9 }
Listing 5: Ví dụ về khai báo mãng
Ta nhận được kết quả:
1 [123]
2 [5 10 15 20]
Và để có thể truy cập vào phần tử của mãng theo index, ta có thể sử dụng syntax tương tự với C+ +, thông qua đó ta cũng có thể thay đổi giá trị của phần tử đó, ví dụ như sau:
1 package main
2 import ( " fmt " )
3
4 func main () {
5 nums := [3] int {8 , 11 , 22}
6 fmt Println ( nums [2])
7 nums [2] = 100
8 fmt Println ( nums )
9 }
Listing 6: Ví dụ về truy cập phần tử của mãng
Ta nhận được kết quả như sau:
1 22
2 [8 11 100]
Ngoài ra, ta có thể lấy được độ dài của mãng thông qua hàm len(), ví dụ:
1 package main
2 import ( " fmt " )
3
5 a := [5] string { "x" , "y" , "z" , "t" , "k" }
7
8 fmt Println ( len ( a ) )
9 fmt Println ( len ( b ) )
10 }
Listing 7: Ví dụ về hàm len()
Ta nhận được kết quả như sau:
1 5
2 4
2.2.6 Slices
Tương tự như Array thì Slices cũng được dùng để lưu trữ mãng các phần tử, điểm khác biệt ở đây
là với Slices ta có thể thay đổi kích thước của nó, ta có thể tạo ra Slice thông qua 3 cách:
Trang 7• Sử dụng dạng syntax []<datatype><values>.
• Tạo Slice từ Array
• Sử dụng hàm make() với syntax: <slice_name> := make([]<type>, <length>, <capacity>) Khi sử dụng slices, ta sẽ có thể sử dụng 2 hàm là len() để lấy ra số phần tử chứa trong Slice và cap() để lấy ra số phần tử tối đa mà slice có thể đạt được trước khi nó grow hơn nữa Ta lấy ví dụ việc tạo ra slice và sử dụng 2 hàm trên như sau:
1 package main
2 import ( " fmt " )
3
5 a := [] string { "SG" , "TS" , "LG" , "TD" } // Create slice
6 fmt Printf ( "a= %v\n" , a )
7 fmt Printf ( " length = %d\n" , len ( a ) )
8 fmt Printf ( " capacity = %d\n" , cap ( a ) )
9
10 array1 := [6] int {10 , 11 , 12 , 13 , 14 , 15}
11 b := array1 [2:4] // Create slice from an array
12 fmt Printf ( "b= %v\n" , b )
13 fmt Printf ( " length = %d\n" , len ( b ) )
14 fmt Printf ( " capacity = %d\n" , cap ( b ) )
15
16 c := make ([] int , 5 , 10) // Create slice with make ()
17 fmt Printf ( "c= %v\n" , c )
18 fmt Printf ( " length = %d\n" , len ( c ) )
19 fmt Printf ( " capacity = %d\n" , cap ( c ) )
20 }
Listing 8: Ví dụ về slice
Ta nhận được kết quả như sau:
1 a = [ SG TS LG TD ]
7 c = [0 0 0 0 0]
Thực chất, Slice như một tham chiếu đến Array, nó mô tả một phần (hoặc toàn bộ) Array Nó có kích thước động nên thường được sử dụng nhiều hơn Array
Để có thể truy xuất, thay đổi giá trị của một phần tử trong slice ta có thể thực hiện tương tự đối với array
Và như đã được đề cập ở trên, slice có thể thay đổi kích thước, thêm bớt phần tử hoặc nối 2 slice thông qua hàm append() như ví dụ sau:
1 package
2 import ( " fmt " )
3
9 fmt Printf ( "a=%v\n" , a )
10 fmt Printf ( "c=%v\n" , c )
11 }
Ta nhận được kết quả như sau:
Trang 81 a =[1 2 3 8
Trang 92.2.7 Câu lệnh điều kiện và câu lệnh switch
Syntax của câu lệnh điều kiện if của Golang tương tự với ngôn ngữ C++
if <condition> {
/ code to be executed if condition is true }else {
/ code to be executed if condition is false }
Ta có thể lấy ví dụ như sau để thấy nhiều cách sử dụng if else:
1 package main
2 import ( " fmt " )
3
4 func main () {
5 temp := 45
6 if ( temp < 18) {
7 fmt Println ( "a" ) 8 }
else {
9 fmt Println ( "b" )
10 }
11
12 if ( temp > 100) {
13 fmt Println ( "c" )
14 } else if ( temp > 50) {
15 fmt Println ( "d" )
16 } else {
17 fmt Println ( "e" )
18 }
19 }
Listing 10: Ví dụ về câu lệnh if
Ta nhận được kết quả như sau:
1 b
2 e
Ngoài ra Golang cũng cung cấp câu lệnh switch case để so sánh giá trị với các giá trị khác nhau
và thực hiện các câu lệnh theo ý người lập trình với syntax như sau:
switch <expression> {
case x:
/ code block case y:
/ code block case z:
default:
/ code block }
Câu lệnh sẽ so sánh giá trị ở expression với các giá trị ở từng case, nếu bằng nhau thì câu lệnh ở phần case đó sẽ được chạy Phần default thì là optimal, có thể có hoặc không Ta có thể lấy ví dụ như sau:
1 package main
2 import ( " fmt " )
3
4 func main () {
5 num := 2
6
7 switch num {
8 case 1:
9 fmt Println ( " One" )
10 case 2:
11 fmt Println ( " Two" )
12 case 3:
13 fmt Println ( " Three " )
14 }
15 }
Listing 11: Ví dụ về câu lệnh switch
Trang 10Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học & Kỹ Thuật Máy Tính
Ta nhận được kết quả như sau:
1 Two
2.2.8 Vòng lặp
Để sử dụng vòng lặp trong Go, ta chỉ có thể sử dụng for (Không có while) thông qua 2 syntax sau:
for <statement1>; <statement2>;<statement3> {
// code to be executed for each iteration }
• <statement1>: Để khởi tạo giá trị biến đếm
• <statement2>: Điều kiện tiếp tục vòng lặp sau mỗi lần lặp
• <statement3>: Cập nhật giá trị biến đếm sau mỗi lần lặp
Ta có thể lấy ví dụ như sau:
1 package main
2 import ( " fmt " )
3
6 fmt Print (i , " " )
7 }
8 }
Listing 12: Ví dụ về câu lệnh for
Ta nhận được kết quả như sau:
1 0123456789
Với cách sử dụng for tiếp theo, ta có thể sử dụng từ khóa range như sau:
for <index>, <value> := <array|slice|map> {
// code to be executed for each iteration }
Để có thể hình dung rõ hơn, ta xem ví dụ sau:
1 package main
2 import ( " fmt " )
3
7 fmt Printf ( "%v %v\n" , idx , val )
8 }
9 }
Listing 13: Ví dụ về câu lệnh for với range
Ta nhận được kết quả như sau:
1 0 Selena Gomez
2 1 Taylor Swift
3 2 Harry Styles
2.2.9 Hàm
Với các ngôn ngữ lập trình thì việc sử dụng function là vô cùng cần thiết, với Go ta có thể định
nghĩa ra các hàm thông qua từ khóa func và với syntax cụ thể như sau:
func <FunctionName>(<param1> <type>, <param2> <type>, <param3> <type>) { //
code to be executed }
Ngoài hàm chính ra thì các hàm chỉ được thực thi khi được gọi, sau đây là một ví dụ để gọi hàm
không có tham số và có tham số:
Trang 111 package main
2 import ( " fmt " )
3
4 func d o S o m e t h i n g () {
5 fmt Println ( " Advanced P r o g r a m m i n g is fun !" )
6 }
7 func p ri nt N am e ( name string ) {
8 fmt Println ( "My name is" , name )
9 }
10 func main () {
11 d o S o m e t h i n g ()
12 p ri nt N am e ( " Dat " )
13 p ri nt N am e ( " Mason Luong " )
14 }
Listing 14: Ví dụ về hàm
Ta nhận được kết quả như sau:
1 Advanced P r o g r a m m i n g is fun !
2 My name is Dat
3 My name is Mason Luong
Ngoài ra ta cũng có thể trả về giá trị kết quả của hàm, với Go ta còn có thể đặt trước tên biến sẽ lưu kết quả trả về, khi trả về chỉ cần ghi return trống Ta lấy ví dụ 2 hàm một hàm không đặt tên biến trả về và một hàm có như sau:
1 package main
2 package main
3 import ( " fmt " )
4
5 func add ( x int , y int ) int {
6 return x + y
7 }
8 func product ( x int , y int ) ( result int ) {
9 result = x * y
10 return
11 }
12 func main () {
13 fmt Println ( add (3 , 4) )
14 fmt Println ( product (3 , 4) )
15 }
Listing 15: Ví dụ về hàm
Ta nhận được kết quả như sau:
1 7
2 12
Đặc biệt hơn nữa ta còn có thể trả về một lượt nhiều giá trị và gán nó vào các biến của chương trình, ví dụ như sau:
1 package main
2 import ( " fmt " )
3
4 func a d d A n d M u l t i ( x int , y int ) ( res1 int , res2 int ) {
5 res1 = x + y
6 res2 = x * y
7 return
8 }
9
10 func main () {
11 a , b := a d d A n d M u l t i (4 ,5)
12 fmt Println (a , b )
13 }
Listing 16: Ví dụ về hàm
Ta nhận được kết quả như sau:
1 920
Trang 12Trường Đại Học Bách Khoa Tp.Hồ Chí Minh
Khoa Khoa Học & Kỹ Thuật Máy Tính
Trong một vài trường hợp, bạn sử dụng hàm trả về nhiều giá trị nhưng bạn chỉ quan tâm đến một kết quả nào đó thì bạn có thể sử dụng dấu "_" để loại bỏ giá trị đó đi, lấy ví dụ:
1 package main
2 import ( " fmt " )
3
4 func a d d A n d M u l t i ( x int , y int ) ( res1 int , res2 int ) {
5 res1 = x + y
6 res2 = x * y
7 return
8 }
9
10 func main () {
11 _ , b := a d d A n d M u l t i (5 ,6)
12 fmt Println ( b )
13 }
Listing 17: Ví dụ về hàm
Ta nhận được kết quả như sau:
1 30
2.2.10 Struct
Để tạo ra những tập hợp những dữ liệu khác nhau, kiểu khác nhau thì ta sẽ sử dụng struct Với
Go, ta có thể sử dụng syntax như sau để khai báo một kiểu mới:
type <struct_name> struct {
<member1> <datatype>;
<member2> <datatype>;
<member3> <datatype>;
}
Sau khi định nghĩa một struct mới, ta có thể khai báo những biến thuộc kiểu struct đó và sử dụng,
và để truy cập vào hay thay đổi dữ liệu của struct ta có thể sử dụng operator dấu chấm "." Ta sẽ lấy ví
dụ như sau:
1 package main
2 import ( " fmt " )
3
4 type Singer struct {
5 name string
6 genre string
7 age int
8 }
9
10 func main () {
11 var s1 Singer
12 var s2 Singer
13
14 // s1 s p e c i f i c a t i o n
15 s1 name = " Selena Gomez "
16 s1 genre = " Pop "
17 s1 age = 29
18
19 // s2 s p e c i f i c a t i o n
20 s2 name = " Taylor Swift "
21 s2 genre = " Folk "
22 s2 age = 33
23
24 // Access and print s1 info
25 fmt Println ( " Name : " , s1 name )
26 fmt Println ( " Genre : " , s1 genre )
27 fmt Println ( " Age: " , s1 age )
28
29 // Access and print s2 info
30 fmt Println ( " Name : " , s2 name )
31 fmt Println ( " Genre : " , s2 genre )
32 fmt Println ( " Age: " , s2 age )