0
0
Lập trình
Harry Tran
Harry Tran106580903228332612117

Ngày thứ 2 trong hành trình học Golang

Đăng vào 5 giờ trước

• 5 phút đọc

Giới thiệu

Hôm nay là ngày thứ 2 trong hành trình học Golang của tôi. Tôi quyết định ghi lại quá trình học tập để không chỉ giúp bản thân mà còn kết nối với những người cũng đang khám phá ngôn ngữ lập trình này. Trong bài viết này, tôi sẽ đi sâu vào các khái niệm quan trọng của Golang bao gồm: Closures, Đệ quy, Con trỏ, Chuỗi và Runes, Verb định dạng và gói fmt, Structs và Phương thức, Interfaces, Kế thừa Struct, và Generics.


Mục lục

  1. Closures
  2. Đệ quy
  3. Con trỏ
  4. Chuỗi và Runes
  5. Verb định dạng và gói fmt
  6. Structs và Phương thức
  7. Interfaces
  8. Kế thừa Struct
  9. Generics
  10. Thực hành tốt nhất
  11. Cạm bẫy phổ biến
  12. Mẹo hiệu suất
  13. Khắc phục sự cố

Closures

Khái niệm

Closures là một trong những tính năng mạnh mẽ của Golang. Nó cho phép bạn định nghĩa một hàm bên trong một hàm khác và hàm bên trong có thể truy cập các biến của hàm bên ngoài.

Ví dụ

go Copy
package main
import (
    "fmt"
)

func main() {
    x := 10
    closureFunc := func(y int) int {
        return x + y
    }
    fmt.Println(closureFunc(5)) // Kết quả: 15
}

Lưu ý

  • Đảm bảo rằng biến bên ngoài vẫn còn tồn tại trong phạm vi khi hàm closure được gọi.
  • Cẩn thận với việc thay đổi giá trị của biến bên ngoài trong hàm closure, điều này có thể gây ra lỗi không mong muốn.

Đệ quy

Khái niệm

Đệ quy là kỹ thuật gọi hàm trong chính nó. Trong Golang, điều này rất hữu ích cho các bài toán như tính giai thừa hoặc tìm kiếm trong cấu trúc dữ liệu.

Ví dụ

go Copy
package main
import (
    "fmt"
)

func factorial(n int) int {
    if n == 0 {
        return 1
    }
    return n * factorial(n-1)
}

func main() {
    fmt.Println(factorial(5)) // Kết quả: 120
}

Thực hành tốt nhất

  • Đặt điều kiện dừng rõ ràng để tránh việc gọi đệ quy vô hạn.
  • Kiểm tra độ sâu của đệ quy để tránh lỗi tràn ngăn xếp.

Con trỏ

Khái niệm

Con trỏ trong Golang cho phép bạn làm việc với địa chỉ bộ nhớ của các biến, giúp tiết kiệm bộ nhớ và tăng hiệu suất.

Ví dụ

go Copy
package main
import (
    "fmt"
)

func main() {
    x := 10
    ptr := &x
    fmt.Println(*ptr) // Kết quả: 10
    *ptr = 20
    fmt.Println(x) // Kết quả: 20
}

Cạm bẫy phổ biến

  • Nên cẩn trọng khi sử dụng con trỏ để tránh các lỗi liên quan đến bộ nhớ.
  • Đảm bảo rằng bạn không tham chiếu đến địa chỉ đã được giải phóng.

Chuỗi và Runes

Khái niệm

Golang phân biệt giữa chuỗi và runes. Runes là kiểu dữ liệu đại diện cho một ký tự Unicode.

Ví dụ

go Copy
package main
import (
    "fmt"
)

func main() {
    str := "Hello, 世界"
    for _, r := range str {
        fmt.Printf("Ký tự: %c \n", r)
    }
}

Lưu ý

  • Sử dụng runes để xử lý chuỗi đa ngôn ngữ một cách chính xác.

Verb định dạng và gói fmt

Khái niệm

Gói fmt cung cấp các hàm định dạng cho đầu vào và đầu ra. Điều này rất hữu ích cho việc xây dựng các ứng dụng CLI.

Ví dụ

go Copy
package main
import (
    "fmt"
)

func main() {
    name := "Golang"
    fmt.Printf("Chào mừng đến với %s!\n", name)
}

Structs và Phương thức

Khái niệm

Structs là cách tổ chức dữ liệu trong Golang. Bạn có thể định nghĩa các phương thức cho structs để làm việc với chúng.

Ví dụ

go Copy
package main
import (
    "fmt"
)

type Person struct {
    Name string
    Age  int
}

func (p Person) Greet() {
    fmt.Printf("Chào %s, bạn %d tuổi!\n", p.Name, p.Age)
}

func main() {
    person := Person{Name: "An", Age: 30}
    person.Greet()
}

Interfaces

Khái niệm

Interfaces trong Golang cho phép bạn định nghĩa các phương thức mà không cần xác định kiểu dữ liệu cụ thể. Điều này tạo ra tính linh hoạt trong lập trình.

Ví dụ

go Copy
package main
import (
    "fmt"
)

type Speaker interface {
    Speak() string
}

type Dog struct {}

type Cat struct {}

func (d Dog) Speak() string {
    return "Gau Gau"
}

func (c Cat) Speak() string {
    return "Meo Meo"
}

func main() {
    var s Speaker
    s = Dog{}
    fmt.Println(s.Speak()) // Kết quả: Gau Gau
    s = Cat{}
    fmt.Println(s.Speak()) // Kết quả: Meo Meo
}

Kế thừa Struct

Khái niệm

Golang cho phép bạn kế thừa các thuộc tính của một struct khác thông qua embedding.

Ví dụ

go Copy
package main
import (
    "fmt"
)

type Animal struct {
    Name string
}

type Dog struct {
    Animal
}

func main() {
    d := Dog{Animal: Animal{Name: "Bulldog"}}
    fmt.Println(d.Name) // Kết quả: Bulldog
}

Generics

Khái niệm

Generics cho phép bạn viết mã mà không cần chỉ định kiểu cụ thể, giúp tăng tính tái sử dụng.

Ví dụ

go Copy
package main
import (
    "fmt"
)

func Print[T any](value T) {
    fmt.Println(value)
}

func main() {
    Print(10)
    Print("Hello")
}

Thực hành tốt nhất

  • Luôn viết mã rõ ràng và có chú thích.
  • Kiểm tra mã của bạn thường xuyên để đảm bảo tính chính xác.

Cạm bẫy phổ biến

  • Đừng bỏ qua việc xử lý lỗi trong mã của bạn.
  • Tránh việc lạm dụng các tính năng phức tạp mà không cần thiết.

Mẹo hiệu suất

  • Sử dụng các công cụ profiling để tối ưu hóa mã của bạn.
  • Tránh việc tạo ra các đối tượng không cần thiết trong vòng lặp.

Khắc phục sự cố

  • Nếu bạn gặp lỗi biên dịch, hãy kiểm tra lại các biến và kiểu dữ liệu.
  • Đối với lỗi runtime, sử dụng panicrecover để xử lý ngoại lệ.

Kết luận

Học Golang là một hành trình thú vị và đầy thử thách. Hy vọng rằng những kiến thức mà tôi đã chia sẻ sẽ giúp ích cho những ai đang bắt đầu hoặc muốn nâng cao kỹ năng lập trình của mình. Hãy tiếp tục theo dõi để cùng tôi khám phá thêm nhiều điều thú vị trong các bài tiếp theo!


Câu hỏi thường gặp

1. Golang có những ứng dụng gì?
Golang thường được sử dụng trong phát triển web, hệ thống phân tán và các ứng dụng cần hiệu suất cao.
2. Làm thế nào để bắt đầu với Golang?
Bạn có thể bắt đầu bằng cách cài đặt Go và thực hành với các bài tập cơ bản.
3. Có tài liệu nào hữu ích cho việc học Golang không?
Có rất nhiều tài liệu trực tuyến như Go by Example, Tour of Go, và tài liệu chính thức của Go.

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào