Giới thiệu ngôn ngữ lập trình GoLang
Go là một ngôn ngữ lập trình được thiết kế dựa trên tư duy lập trình hệ thống. Go được phát triển bởi Robert Griesemer, Rob Pike và Ken Thompson tại Google vào năm 2007. Điểm mạnh của Go là bộ thu gom rác và hỗ trợ lập trình đồng thời (tương tự như đa luồng – multithreading). Go là một ngôn ngữ ...
Go là một ngôn ngữ lập trình được thiết kế dựa trên tư duy lập trình hệ thống. Go được phát triển bởi Robert Griesemer, Rob Pike và Ken Thompson tại Google vào năm 2007. Điểm mạnh của Go là bộ thu gom rác và hỗ trợ lập trình đồng thời (tương tự như đa luồng – multithreading). Go là một ngôn ngữ biên dịch như C/C++, Java, Pascal… Go được giới thiệu vào năm 2009 và được sử dụng hầu hết trong các sản phẩm của Google.
Một số đặc điểm
- Hỗ trợ khai báo kiểu dữ liệu động
- Tốc độ biên dịch nhanh
- Hỗ trợ các tác vụ đồng thời
- Ngôn ngữ đơn giản, ngắn gọn
Tuy nhiên chính vì muốn ngôn ngữ này trở nên cực kỳ đơn giản mà các nhà phát triển đã loại bỏ một số tính năng (mà mình cho là hữu ích) có trong các ngôn ngữ khác như:
- Không hỗ trợ thừa kế
- Không hỗ trợ quá tải toán tử hoặc ghi đè phương thức
- Không hỗ trợ thao tác trên con trỏ (vì lý do bảo mật)
- Không hỗ trợ kiểu Generic (giống như template trong C++)
Integer
Các kiểu số nguyên trong Go là uint8, uint16, uint32, uint64, int8, int16, int32, int64. Các con số 8, 16, 32, 64 có nghĩa là máy tính cần dùng bao nhiêu bit để biểu diễn số nguyên đó. uint tức là unsigned int – là kiểu số nguyên không âm. Bảng dưới đây cho biết giới hạn của từng loại kiểu số nguyên:
KIỂU GIỚI HẠN uint8 0 – 255 uint16 0 – 65535 uint32 0 – 4294967295 uint64 0 – 18446744073709551615 int8 -128 – 127 int16 -32768 – 32767 int32 -2147483648 – 2147483647 int64 -9223372036854775808 – 9223372036854775807
Kiểu uint8 còn có tên khác là byte, kiểu int32 có tên khác là rune.
Đặc biệt trong Go còn có 3 kiểu số nguyên phụ thuộc hệ điều hành là uint, int và uintptr, 3 kiểu dữ liệu này có giới hạn giống như kiến trúc của hệ điều hành mà bạn đang sử dụng. Ví dụ nếu bạn đang dùng Windows 64 bit thì kiểu int sẽ có giới hạn giống như kiểu uint64. Thông thường khi sử dụng số nguyên bạn dùng int là đủ rồi. Ví dụ: main.go
package main import "fmt" func main() { fmt.Println("1 + 1 = ", 1 + 1) }
kết quả:
$ go run main.go 1 + 1 = 2
Float
Đây là các giá trị số có phần thập phân, ví dụ 1.234, 123.4… Việc lưu trữ cũng như thao tác với số thực trong máy tính khá phức tạp nên chúng ta cũng không đi sâu vào làm gì. Ở đây chúng ta chỉ có một số lưu ý như sau:
Số thực không bao giờ chính xác một cách tuyệt đối, rất khó để biểu diễn chính xác một số thực. Ví dụ như phép trừ 1.01 – 0.99 sẽ cho ra kết quả là 0.020000000000000018 chứ không phải là 0.02 như bạn vẫn nghĩ. Cũng giống như số nguyên, số thực trong máy tính cũng có nhiều giới hạn khác nhau. Trong Go có 2 kiểu số thực là float32 và float64, 2 kiểu số phức là complex64 và complex128. Thông thường để biểu diễn số thực, bạn chỉ cần dùng float64 là đủ.
String
String (chuỗi) là các kí tự được bọc trong cặp dấu nháy kép hoặc nháy đơn được dùng để biểu diễn văn bản. String nằm trong dấu nháy kép có thể sử dụng các kí tự điều khiển đặc biệt như là xuống dòng, là dấu tab.
Chúng ta có thể thực hiện một số thao tác thường dùng trên String như tính độ dài chuỗi, lấy kí tự tại vị trí nhất định, nối chuỗi. Ví dụ: string.go
package main import "fmt" func main() { fmt.Println(len("Hello World")) fmt.Println("Hello World"[1]) fmt.Println("Hello " + "World") }
Dấu cách cũng được tính là một kí tự, do đó chiều dài chuỗi “Hello World” là 11.
Các kí tự trong một chuỗi được đánh số thứ tự từ 0. Câu lệnh “Hello World”[1] sẽ cho ra kết quả là kí tự ở vị trí số 2, tuy nhiên nếu bạn chạy đoạn code trên thì kết quả sẽ cho ra là số 101 chứ không phải kí tự ‘e’, là bởi vì 101 là mã ASCII của kí tự ‘e’
Chúng ta có thể dùng phép toán + lên 2 chuỗi, kết quả là một chuỗi mới được nối từ 2 chuỗi đầu. kết quả
11 101 Hello World
Boolean
Các giá trị boolean là các giá trị 1 bit, có 2 giá trị là true và false được dùng để biểu diễn ý nghĩa ĐÚNG hoặc SAI. Trong Go có 3 phép toán có thể thao tác với giá trị boolean là && (phép AND), || (phép OR) và ! (phép NOT).
Bảng dưới đây mô tả cách thực hiện phép toán với kiểu boolean:
Phép AND:
BIỂU THỨC GIÁ TRỊ true && true true true && false false false && true false false && false false
Phép OR:
BIỂU THỨC GIÁ TRỊ true || true true true || false true false || true true false || false false
Phép NOT:
BIỂU THỨC GIÁ TRỊ !true false !false true
Ví dụ:
package main import "fmt" func main() { fmt.Println(true && false) fmt.Println(true && false) fmt.Println(true || true) fmt.Println(true || false) fmt.Println(!true) }
Kết quả:
true false true true false
Biến là nơi lưu trữ dữ liệu, một biến gồm có 2 phần là tên biến và kiểu dữ liệu. Ví dụ:
variables.go
package main import "fmt" func main() { var x string = "Hello World" fmt.Println(x) }
Đoạn code chương trình trên in ra dòng chữ Hello World như trong các bài trước, nhưng thay vì chúng ta đưa chuỗi Hello World trực tiếp vào trong hàm Println() thì ở đây chúng ta gán vào một biến có tên là x.
Để khai báo một biến trong Go thì chúng ta dùng từ khóa var, theo sau là tên biến, rồi đến kiểu dữ liệu, cuối cùng chúng ta có thể gán giá trị cho biến hoặc gán sau cũng được. Ví dụ:
variables_2.go
package main import "fmt" func main() { var x string x = "Hello World" fmt.Println(x); }
Biến trong Go nói riêng hay lập trình nói chung thì cũng tương đương như biến mà chúng ta được học trong toán, tuy nhiên có một điểm hơi khác đó là biến trong lập trình thì có thể thay đổi giá trị được, ví dụ:
variables_3.go
package main import "fmt" func main() { var x string x = "first" fmt.Println(x) x = "second" fmt.Println(x) }
Cũng vì thế cách phát biểu về một giá trị của biến cũng khác đi. Chẳng hạn như khi gặp dòng x="Hello World", bạn có thể nói “x bằng Hello World”, tuy nhiên nói đúng hơn là “x nhận giá trị Hello World”, hoặc “x được gán giá trị Hello World”.
Ngoài ra thường trong lập trình chúng ta hay khai báo một biến rồi sau đó gán giá trị cho nó luôn nên Go cho phép chúng ta khai báo và gán giá trị nhanh như sau:
x := "Hello World" Ở đây chúng ta không dùng từ khóa var, không khai báo kiểu dữ liệu, thay vào đó chúng ta ghi tên biến rồi dùng toán tử := theo sau là giá trị để khai báo nhanh một biến và gán giá trị ngay tại chỗ. Trình biên dịch Go sẽ tự động nhận diển kiểu dữ liệu dựa vào giá trị mà bạn gán cho biến. Chẳng hạn như ở đây Go thấy giá trị là “Hello World”, tức là một string nên sẽ tự động cho biến x kiểu dữ liệu string. Tóm lại 2 dòng sau đây có chức năng y hệt nhau:
var x string = "Hello World" x := "Hello World"
Đặt tên biến Tên biến có thể có một hoặc nhiều kí tự, có thể chứa chữ cái, dấu gạch dưới _ và chữ số. Kí tự đầu tiên phải là chữ cái hoặc dấu gạch dưới.
Go không quan tâm bạn đặt tên biến như thế nào, nên khi đặt thì chúng ta nên đặt sao cho dễ nhớ và dễ hiểu. Ví dụ:
title := "Pho Code" fmt.Println("Website name: ", title)
Phạm vi hoạt động của biến Chúng ta viết lại chương trình Hello World ở trên như sau:
scope.go
package main import "fmt" var x string = "Hello World" func main() { fmt.Println(x) }
Ở đây chúng ta đưa dòng khai báo biến x ra ngoài hàm main(). Làm như thế biến x sẽ có thể truy cập bởi bất kì hàm nào. Ví dụ:
var x string = "Hello World" func main() { fmt.Println(x) } func f() { fmt.Println(x) }
Trong đoạn code trên hàm f() có thể đọc được giá trị của biến x. Giả sử chúng ta đưa biến x vào lại bên trong hàm main như sau:
func main() { var x string = "Hello World" fmt.Println(x) } func f() { fmt.Println(x) }
Đoạn code trên khi biên dịch sẽ báo lỗi như sau:
Output main.go:11: undefined: x Dòng báo lỗi trên có nghĩa là biến x không tồn tại. Bởi vì nó chỉ được khai báo ở trong hàm main() nên chỉ có thể đọc được ở trong hàm main(). Chính xác hơn là một biến chỉ có thể được đọc ở trong cặp dấu ngoặc nhọn gần nhất {} theo tài liệu của Go.
Hằng số Hằng số đơn giản chỉ là các biến không thể thay đổi dược giá trị. Cách khai báo và gán giá trị cho hằng số cũng giống như với biến, chỉ khác một chỗ là thay từ khóa var bằng từ khóa const. Ví dụ:
constants.go
package main import "fmt" func main() { const x string = "Hello World" fmt.Println(x) }
Chúng ta không thể thay đổi giá trị của hằng số.
const x string = "Hello World" x = "Goodbye World"
Đoạn code trên sẽ báo lỗi như sau:
Output main.go:7: cannot assign to x Hằng số thường được dùng để lưu các giá trị dùng nhiều lần mà không cần phải khai báo lại. Trong Go có rất nhiều hằng số được tạo sẵn, ví dụ như hằng Pi trong gói math.
Khai báo nhiều biến Ngoài cách khai báo từng biến trên một dòng, bạn có thể khai báo nhiều biến một lúc như sau:
var ( a = 5 b = 10 c = 15 )
Chúng ta dùng từ khóa var (hoặc const), theo sau là cặp dấu ngoặc tròn (), rồi tới danh sách các biến và giá trị của chúng.
Lệnh for
Giả sử chúng ta cần in các con số từ 1 đến 10 ra màn hình, chúng ta có thể ghi 10 câu lệnh fmt.Println() như sau:
package main import "fmt" func main() { fmt.Println(1) fmt.Println(2) fmt.Println(3) fmt.Println(4) fmt.Println(5) fmt.Println(6) fmt.Println(7) fmt.Println(8) fmt.Println(9) fmt.Println(10) }
Lệnh for cho phép lặp đi lặp lại các câu lệnh nhiều lần. Ví dụ:
for.go
package main import "fmt" func main() { var i int = 1 for i <= 10 { fmt.Println(i) i = i + 1 } }
Đoạn code trên sẽ in các chữ số từ 1 đến 10 ra màn hình, thay vì phải dùng 10 câu lệnh fmt.Println() thì bây giờ chúng ta chỉ cần dùng câu lệnh for là đủ.
Trong đoạn code trên, chúng ta khai báo biến i và gán giá trị là 1. Sau đó chúng ta sử dụng lệnh for để chạy câu lệnh fmt.Println() 10 lần bằng cách ghi từ khóa for, theo sau là một biểu thức điều kiện i <= 10, rồi tới khối lệnh nằm trong cặp dấu ngoặc nhọn {}.
Khi câu lệnh for bắt đầu chạy, đầu tiên câu lệnh này kiểm tra xem biến i có giá trị bé hơn 10 hay không, nếu đúng thì thực hiện những câu lệnh bên dưới, rồi quay ngược lại kiểm tra i cho đến khi nào i không còn bé hơn 10 thì dừng lại. Do đó chúng ta đặt lệnh i = i + 1 bên trong vòng lặp, cứ mỗi lần lặp giá trị của biến i sẽ được tăng lên 1 cho đến khi i = 10 thì vòng lặp for sẽ thoát.
Output
1 2 3 4 5 6 7 8 9 10
Chúng ta có thể đưa câu lệnh khai báo biến và lệnh tăng giá trị của biến ngay trên một dòng như sau:
for2.go
func main() { for i := 1; i <= 10 ; i++ { fmt.Println(i) } }
Hâu hết các ngôn ngữ khác có rất nhiều lệnh lặp như while, do, until, foreach.... nhưng Go chỉ hỗ trợ một lệnh lặp duy nhất là lệnh for.
Lệnh if
Bây giờ chúng ta thử in các con số từ 1 đến 10 và cho biết số đó là chẵn hay lẻ. Để làm điều này thì chúng ta sẽ cần dùng đến câu lệnh if. Ví dụ:
if.go
package main import "fmt" func main() { for i := 1; i <= 10 ; i++ { if i % 2 == 0 { fmt.Println(i, "chan") } else { fmt.Println(i, "le") } } }
Ở đây chúng ta sử dụng câu lệnh if để kiểm tra xem biến i mang giá trị là số chẵn hay lẻ. Chúng ta ghi câu lệnh if, theo sau là một biểu thức điều kiện (tức là kết quả phải là true hoặc false), rồi đến khối lệnh nằm trong cặp dấu ngoặc nhọn {}, sau đó chúng ta có thể có thêm các câu lệnh else if hoặc else.
Nếu biểu thức điều kiện phía sau if là true thì thực hiện câu khối lệnh phía sau nó, ngược lại thì tiếp tục kiểm tra các biểu thức điều kiện tiếp theo nếu có.
Ở đây biểu thức điều kiện là câu lệnh i % 2 == 0, tức là chúng ta kiểm tra xem i có chia hết cho 2 hay không (hay i chia cho 2 không dư), nếu đúng thì i là số chẵn.
Output
1 le 2 chan 3 le 4 chan 5 le 6 chan 7 le 8 chan 9 le 10 chan
Lệnh switch
Giả sử chúng ta muốn in các chữ số bằng chữ, chúng ta có thể viết đoạn code như sau:
if i == 0 { fmt.Println("Khong") } else if i == 1 { fmt.Println("Mot") } else if i == 2 { fmt.Println("Hai") } else if i == 3 { fmt.Println("Ba") } else if i == 4 { fmt.Println("Bon") } else if i == 5 { fmt.Println("Nam") }
Thay vì dùng câu lệnh if như trên, chúng ta có thể dùng câu lệnh switch như sau:
switch i { case 0: fmt.Println("Khong") case 1: fmt.Println("Mot") case 2: fmt.Println("Hai") case 3: fmt.Println("Ba") case 4: fmt.Println("Bon") case 5: fmt.Println("Nam") default: fmt.Println("Khong biet") }
Chúng ta dùng từ khóa switch, theo sau là một biểu thức điều kiện, rồi tới một danh sách các từ khóa case, ứng với mỗi từ khóa case là một giá trị nào đó, rồi tới dấu 2 chấm : và các lệnh sẽ được thực hiện.
Ý nghĩa của lệnh switch là, nếu biểu thức điều kiện ở switch cho kết quả trùng với giá trị ở từ khóa case nào thì thực hiện các câu lệnh sau từ khóa case đó. Ngoài ra ở đây chúng ta còn có từ khóa default, có tác dụng thực hiện các câu lệnh nếu giá trị ở switch không trùng với bất kì từ khóa case nào. Các bạn có thể tìm hiểu sâu hơn ở đây: Nguồn: https://phocode.com/golang/go-lap-trinh-go/ Book: https://www.golang-book.com/books/intro