Gói lệnh (Package)
Mỗi chương trình Go được tổ chức thành các gói. Từ khóa package khai báo tên gói, còn import dùng để nhập các gói cần thiết. Tên gói được đặt trong cặp dấu ngoặc kép. Các định danh (identifier) được xuất ra ngoài gói phải bắt đầu bằng chữ cái viết hoa.
package main
import "fmt"
import "math"
import (
"fmt"
"math"
)
func main() {
fmt.Println(math.Pi)
}
Hàm
Hàm trong Go được khai báo bằng từ khóa func. Go sử dụng cú pháp kiểu dữ liệu đặt sau tên (type後置). Khi nhiều tham số có cùng kiểu, có thể gộp khai báo. Go hỗ trợ trả về nhiều giá trị, tương tự tuple trong một số ngôn ngữ khác, và các giá trị trả về có thể được đặt tên.
func add(a int, b int) int {
return a + b
}
func add(a, b int) int {
return a + b
}
func swap(str1, str2 string) (string, string) {
return str2, str1
}
func divide(total int) (first, second int) {
first = total * 3 / 7
second = total - first
return
}
Biến và hằng số
Biến được khai báo bằng từ khóa var, cũng sử dụng cú pháp kiểu dữ liệu đặt sau tên. Có thể gộp khai báo nhiều biến cùng kiểu. Khi khởi tạo biến, nếu giá trị khởi tạo đã xác định rõ kiểu, có thể bỏ qua khai báo kiểu - trình biên dịch sẽ tự suy luận. Nhiều biến có thể được khởi tạo đồng thời. Biến không được khởi tạo tường minh sẽ nhận giá trị mặc định (zero value): 0 cho số, false cho boolean, "" cho chuỗi. Go cung cấp cú pháp viết tắt := để khai báo và khởi tạo biến cùng lúc. Hằng số được khai báo bằng từ khóa const.
var c, python, java bool
var counter int
var counter, total int = 5, 10
var c, python, java = true, false, "khong!"
greeting := "xin chao"
c, python, java := true, false, "khong!"
const Pi = 3.14159
const Welcome = "chao mung"
const IsActive = true
Các kiểu dữ liệu cơ bản
Go cung cấp các kiểu dữ liệu sau:
- bool
- string
- int, int8, int16, int32, int64
- uint, uint8, uint16, uint32, uint64, uintptr
- byte - bí danh của uint8
- rune - bí danh của int32, đại diện cho một điểm mã Unicode
- float32, float64
- complex64, complex128
Go yêu cầu chuyển đổi kiểu tường minh giữa các kiểu dữ liệu khác nhau:
number := 100
decimal := float64(number)
unsigned := uint(decimal)
Câu lệnh điều khiển
Vòng lặp for trong Go có cấu trúc tương tự C nhưng không có dấu ngoặc đơn bao quanh. Ba thành phần của vòng lặp đều có thể bỏ qua. Để tạo vòng lặp dạng while, chỉ cần sử dụng for với điều kiện. Vòng lặp vô hạn có thể viết đơn giản là for {}.
Câu lệnh if có thể đi kèm một câu lệnh khởi tạo trước điều kiện, và biến trong câu lệnh khởi tạo chỉ có phạm vi trong khối if.
Câu lệnh switch cũng hỗ trợ câu lệnh khởi tạo. Khác với C, Go không tự động thực hiện break giữa các case, và giá trị trong case không nhất thiết phải là hằng số. Switch không có điều kiện tương đương với nhiều nhánh if-else.
Từ khóa defer hoãn việc thực thi hàm cho đến khi hàm chứa nó kết thúc. Các lệnh defer được thực hiện theo thứ tự LIFO (last-in-first-out).
// Vòng lặp for cơ bản
total := 0
for idx := 0; idx < 20; idx++ {
total += idx
}
// Ba phần đều có thể bỏ qua
result := 1
for ; result < 500; {
result += result
}
// Dạng while
total := 1
for total < 500 {
total += total
}
// Vòng lặp vô hạn
for {
// thực hiện mãi mãi
}
// if với câu lệnh khởi tạo
if val := math.Pow(base, exp); val < threshold {
return val
} else {
fmt.Printf("%g lon hon hoac bang %g\n", val, threshold)
}
// switch với câu lệnh khởi tạo
switch os := runtime.GOOS; os {
case "darwin":
fmt.Println("Mac OS")
case "linux":
fmt.Println("Linux")
default:
fmt.Printf("%s\n", os)
}
// Switch không có điều kiện
switch {
case time.Now().Hour() < 12:
fmt.Println("Chao buoi sang!")
case time.Now().Hour() < 17:
fmt.Println("Chao buoi chieu")
default:
fmt.Println("Chao buoi toi")
}
// defer hoãn thực thi hàm
func main() {
fmt.Println("bat dau")
for i := 0; i < 5; i++ {
defer fmt.Println(i)
}
fmt.Println("ket thuc")
}
// ket thuc
// 4
// 3
// 2
// 1
// 0
Con trỏ
Go cung cấp con trỏ cho phép thao tác trực tiếp với bộ nhớ. Toán tử & lấy địa chỉ của biến, toán tử * truy cập giá trị tại địa chỉ con trỏ.
num1, num2 := 55, 3301
ptr := &num1
*ptr = 99
ptr = &num2
*ptr = *ptr / 11
Cấu trúc (Struct)
Struct là kiểu dữ liệu tổ hợp cho phép nhóm nhiều trường dữ liệu lại với nhau. Có thể truy cập các trường qua toán tử dấu chấm, hoặc qua con trỏ đến struct.
type Coordinates struct {
Lat int
Long int
}
point := Coordinates{10, 20}
point.Lat = 50
pointer := &point
pointer.Lat = 1e6
var (
p1 = Coordinates{5, 10}
p2 = Coordinates{Lat: 2}
p3 = Coordinates{}
p = &Coordinates{5, 10}
)