Golang cơ bản- Học trong 7 ngày - Part 1 🚀


🎯 Mục tiêu
Giúp bạn và tôi nắm vững kiến thức cơ bản về ngôn ngữ lập trình Go (Golang) chỉ trong 7 ngày, thông qua lý thuyết trọng tâm, thực hành và mini project.
🗓️ Lộ trình học
Ngày | Chủ đề | Mục tiêu học được |
1-2 | Cú pháp cơ bản | Hiểu cách khai báo biến, hằng, hàm, if, for, switch |
3 | Struct, Method, Pointer | Biết dùng struct, method, truyền con trỏ (pointer) |
4 | Slice, Map, Interface | Làm việc với slice, map và xây dựng interface |
5 | Goroutine, Channel | Hiểu lập trình song song với goroutine và channel |
6 | Module, tổ chức project | Tổ chức code với module, chia file và package hợp lý |
7 | Mini Project | Xây dựng project nhỏ áp dụng toàn bộ kiến thức đã học |
📘 Nội dung chi tiết từng ngày
✅ Ngày 1–2: Cú pháp cơ bản
package main
,func main()
Biến:
var
,:=
,const
Hàm: truyền và trả giá trị
Câu lệnh điều kiện:
if
,switch
Vòng lặp:
for
✅ Ngày 3: Struct, Method, Pointer
Tạo
struct
để biểu diễn đối tượngGắn method cho struct
Truyền con trỏ để cập nhật giá trị
✅ Ngày 4: Slice, Map, Interface
Khai báo và thao tác với slice, map
Định nghĩa interface và implement nó với struct cụ thể
✅ Ngày 5: Goroutine, Channel
Tạo goroutine để chạy song song
Giao tiếp giữa các goroutine bằng
chan
✅ Ngày 6: Module, tổ chức project
Sử dụng
go mod
Tổ chức project theo module và package
Chia code ra nhiều file dễ quản lý
✅ Ngày 7: Mini Project
REST API đơn giản với
net/http
hoặcgin
Hoặc CLI tool quản lý việc cần làm
Cấu trúc thư mục, xử lý logic, tách controller, model, utils
🛠️ Yêu cầu trước khi bắt đầu
Đã biết một ngôn ngữ lập trình khác (C, JavaScript, Python,...)
Cài đặt môi trường Go: https://go.dev/doc/install
📚Ngày 1–2: Cú pháp cơ bản trong Golang
1. Package và Hàm Main
Mỗi chương trình Go đều bắt đầu bằng một package, và nếu bạn muốn chương trình chạy được, nó phải có package main và một hàm func main()
.
package main
import "fmt"
func main() {
fmt.Println("Hello, Go!")
}
package main
: Chỉ ra rằng đây là entry point (chương trình chính).func main()
: Hàm main là điểm khởi đầu khi chạy chương trình.
2. Khai báo Biến: var
, :=
, const
var
: Khai báo có kiểu rõ ràng.
var age int = 30
var name string = "Eminel"
:=
: Khai báo nhanh, Go tự suy luận kiểu.
age := 30
name := "Eminel"
Dùng :=
khi bạn đang trong hàm và muốn code gọn hơn. Dùng var
/const
khi khai báo ở ngoài hàm hoặc muốn rõ kiểu.
const
: Khai báo hằng số.
const PI = 3.14
3. Hàm – Truyền và Trả Giá Trị
- Định nghĩa hàm:
func add(a int, b int) int {
return a + b
}
result := add(3, 5) // result = 8
- Hàm có thể trả nhiều giá trị:
func swap(a, b string) (string, string) {
return b, a
}
4. Câu Lệnh Điều Kiện: if
, switch
if
đơn giản:
if age > 18 {
fmt.Println("Adult")
} else {
fmt.Println("Teen")
}
if
có khai báo biến:
if score := 80; score >= 75 {
fmt.Println("Pass")
}
switch
:
switch day := "mon"; day {
case "mon":
fmt.Println("Monday")
case "tue":
fmt.Println("Tuesday")
default:
fmt.Println("Unknown")
}
5. Vòng Lặp: for
Go chỉ có một loại vòng lặp duy nhất là for
, nhưng nó rất linh hoạt.
- Dạng C-style:
for i := 0; i < 5; i++ {
fmt.Println(i)
}
- Dạng while:
i := 0
for i < 5 {
fmt.Println(i)
i++
}
- Lặp qua slice hoặc map:
nums := []int{1, 2, 3}
for index, value := range nums {
fmt.Println(index, value)
}
🔚 Tổng Kết
Chủ đề | Ví dụ |
Biến | var x int = 10 , y := "hello" |
Hàm | func add(a int, b int) int |
If | if x > 10 {} |
Switch | switch x { case 1: ... } |
Vòng lặp | for i := 0; i < 10; i++ {} |
📚 Ngày 3: Struct, Method, Pointer trong Go
✅ 1. Struct – Kiểu dữ liệu có cấu trúc
Struct là cách để gom nhiều trường dữ liệu vào một kiểu:
type Person struct {
name string
age int
}
Khởi tạo struct:
p := Person{name: "Eminel", age: 25}
✅ 2. Method – Hàm gắn với struct
Method giúp gắn hành vi với đối tượng:
func (p Person) Greet() {
fmt.Printf("Xin chào, tôi là %s, %d tuổi.\n", p.name, p.age)
}
(p Person)
gọi là receiver – giúp method nhận dữ liệu từ struct Person
.
✅ 3. Pointer
Con trỏ trong Golang là gì?
Con trỏ (pointer) là một biến dùng để lưu địa chỉ ô nhớ của một biến khác. Nghe có vẻ khó hiểu? Hãy cùng phân tích từng phần.
Biến là gì?
Khi lập trình, ta cần lưu trữ dữ liệu vào bộ nhớ. Mỗi dữ liệu sẽ nằm ở một địa chỉ ô nhớ cụ thể, ví dụ như 0xAFFFF
(địa chỉ dưới dạng hệ thập lục phân).
Để truy cập dữ liệu, ta cần biết địa chỉ ô nhớ nơi dữ liệu được lưu. Nhưng thử tưởng tượng nếu phải nhớ thủ công tất cả địa chỉ đó thì sẽ bất tiện thế nào. Vì vậy, ngôn ngữ lập trình cung cấp biến (variable) – là tên đại diện cho một vùng nhớ.
Vậy con trỏ là gì?
Con trỏ cũng là một biến, nhưng nó đặc biệt ở chỗ giá trị mà nó lưu không phải là số nguyên hay chuỗi thông thường, mà là địa chỉ của một biến khác.
Ví dụ:
var a int = 10
var p *int = &a // p lưu địa chỉ của biến a
Khai báo con trỏ
Cú pháp khai báo một con trỏ trỏ đến kiểu T
:
var p *T
Ví dụ, con trỏ trỏ đến kiểu int
:
var p *int
Con trỏ này chỉ có thể lưu địa chỉ của các biến kiểu int
.
Giá trị mặc định (zero value) của con trỏ là nil
. Khi chưa khởi tạo, con trỏ sẽ có giá trị nil
.
Ví dụ:
package main
import "fmt"
func main() {
var p *int
fmt.Println("p =", p)
}
Kết quả:
p = <nil>
Khởi tạo con trỏ
Bạn có thể gán cho con trỏ địa chỉ của một biến bằng toán tử &
:
var x = 100
var p *int = &x
Toán tử &
giúp lấy địa chỉ của biến x
.
Golang có thể suy luận kiểu của biến con trỏ nên bạn có thể viết gọn:
var p = &x
Ví dụ đầy đủ:
package main
import "fmt"
func main() {
var a = 5.67
var p = &a
fmt.Println("Giá trị của a =", a)
fmt.Println("Địa chỉ của a =", &a)
fmt.Println("Giá trị của p =", p)
}
Truy xuất giá trị qua con trỏ (Dereferencing)
Dùng toán tử *
để lấy giá trị của biến mà con trỏ trỏ đến:
package main
import "fmt"
func main() {
var a = 100
var p = &a
fmt.Println("a =", a)
fmt.Println("p =", p)
fmt.Println("*p =", *p)
}
Toán tử *p
cho ta truy cập và chỉnh sửa giá trị của biến gốc:
*p = 2000
Ví dụ:
var a = 1000
var p = &a
fmt.Println("a (trước) =", a)
*p = 2000
fmt.Println("a (sau) =", a)
Tạo con trỏ bằng hàm new()
Golang cung cấp hàm new()
để tạo con trỏ:
ptr := new(int)
*ptr = 100
fmt.Printf("ptr = %#x, giá trị = %d\n", ptr, *ptr)
Con trỏ trỏ đến con trỏ
Một con trỏ có thể trỏ đến một biến con trỏ khác:
var a = 7.98
var p = &a
var pp = &p
fmt.Println("a =", a)
fmt.Println("*pp =", *pp) // => địa chỉ của a
fmt.Println("**pp =", **pp) // => giá trị của a
Golang không hỗ trợ phép toán con trỏ
Khác với C/C++, Golang không hỗ trợ phép toán trên con trỏ như p + 1
, p - 1
, v.v. Nếu làm vậy sẽ bị lỗi biên dịch.
Tuy nhiên, bạn có thể so sánh hai con trỏ cùng kiểu:
if p1 == p2 {
fmt.Println("Hai con trỏ trỏ cùng một biến.")
}
Kết luận
Con trỏ là biến chứa địa chỉ của biến khác.
Có thể khai báo, khởi tạo và truy cập giá trị qua con trỏ.
Golang không cho phép toán học trên con trỏ như C/C++.
Bạn có thể sử dụng
new()
để tạo con trỏ.
✅ 4. Ví dụ thực tế: Rectangle
type Rectangle struct {
width, height float64
}
func (r Rectangle) Area() float64 {
return r.width * r.height
}
func (r *Rectangle) Resize(newWidth float64) {
r.width = newWidth
}
Area()
không thay đổi dữ liệu → dùngRectangle
(value).Resize()
thay đổi chiều rộng → dùng*Rectangle
(pointer).
🧠 Tổng kết kiến thức
Chủ đề | Ghi nhớ ngắn |
Struct | Gom dữ liệu thành 1 kiểu mới |
Method | Hàm gắn với struct |
Pointer receiver | Thay đổi dữ liệu thật |
Value receiver | Chỉ đọc, không ảnh hưởng tới dữ liệu gốc |
🧠 Ghi nhớ: Nếu bạn muốn method thay đổi dữ liệu gốc, hãy dùng *StructName làm receiver.
📚 Ngày 4: Array, Slice, Map, Interface trong Go
✅ 1. Array – Mảng
Array là một tập hợp các phần tử có cùng kiểu, được lưu trữ liên tục trong bộ nhớ. Kích thước của array là cố định và được xác định khi khai báo.
var arr [3]int // Mảng gồm 3 phần tử kiểu int
arr[0] = 10
Kích thước là một phần của kiểu →
[3]int
khác với[4]int
.Khởi tạo mặc định là zero-value của kiểu dữ liệu.
Array được copy theo giá trị khi truyền vào hàm → cần lưu ý hiệu suất.
✅ 2. Slice – Mảng động
Slice là mảng có kích thước động, dễ thao tác hơn array.
Tính chất
Slice không cần biết trước kích thước.
Có thể thêm phần tử với
append()
.Dùng chung dữ liệu với array hoặc slice khác (cùng underlying array).
👉 Hiểu đơn giản: Slice là như một “khay linh hoạt” – có thể mở rộng thêm ô, nhưng bên dưới vẫn dùng "array thật" làm nền.
Khai báo và thao tác:
nums := []int{1, 2, 3}
nums = append(nums, 4)
for i, v := range nums {
fmt.Println("Index:", i, "Value:", v)
}
Một số hàm với slice:
append(slice, item) – thêm phần tử
len(slice) – độ dài
slice[start:end] – cắt slice
✅ 3. Map – Bản đồ key-value
Map lưu trữ dữ liệu theo cặp key => value.
Tính chất:
Dùng để lưu dữ liệu dạng tên → giá trị (key → value).
Truy cập nhanh, không quan tâm thứ tự.
Có thể kiểm tra xem key có tồn tại không:
👉 Hiểu đơn giản: Map giống như một cái tủ, mỗi ngăn có tên (key), bạn lấy ra giá trị theo tên.
m := map[string]int{"apple": 3, "banana": 5}
fmt.Println(m["apple"]) // in ra 3
Kiểm tra key tồn tại:
val, ok := m["banana"]
if ok {
fmt.Println("Tồn tại:", val)
}
✅ 4. Interface – Giao diện
Interface định nghĩa hành vi (method) mà struct cần triển khai.
Tính chất:
Interface là tập hợp các hành vi (methods).
Một struct tự động triển khai interface nếu có đủ method.
Giúp viết code tổng quát, linh hoạt, dễ mở rộng.
👉 Hiểu đơn giản: Interface giống như "hợp đồng" – nếu một struct ký hợp đồng đó (có đủ phương thức), thì có thể đưa nó vào hệ thống mà không cần biết bên trong là gì.
type Shape interface {
Area() float64
}
Struct nào implement đủ các method thì tự động là interface đó:
type Circle struct {
radius float64
}
func (c Circle) Area() float64 {
return 3.14 * c.radius * c.radius
}
Dùng interface:
func printArea(s Shape) {
fmt.Println("Diện tích:", s.Area())
}
🧠 Tổng kết
Kiến thức | Mô tả ngắn |
Slice | Mảng động, dùng append, range, len |
Map | Bản đồ key => value, thao tác thêm/xóa |
Interface | Định nghĩa hành vi, cho phép xử lý đa hình |
Bài viết này đã dài, tôi xin phép dừng lại tại đây, hẹn gặp các bạn ở phần sau.
Subscribe to my newsletter
Read articles from Eminel directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Eminel
Eminel
Hello, my name is Eminel a software engineer specializing in scalable software architecture, microservices, and AI-powered platforms. Passionate about mentoring, performance optimization, and building solutions that drive business success.