Menu
CoddyTech

Interface Stringer và Error

Thuộc phần Lập trình hướng đối tượng trong hành trình GO của Coddy. Bài học 32 trên 107.

Thư viện chuẩn của Go định nghĩa hai interface mà bạn sẽ thường xuyên sử dụng: fmt.Stringer và error. Cả hai đều là interface đơn giản, chỉ có một phương thức, giúp các kiểu dữ liệu của bạn tích hợp mạnh mẽ với các chức năng tích hợp sẵn của Go.

Giao diện Stringer nằm trong gói fmt và chỉ yêu cầu một phương thức:

type Stringer interface {
    String() string
}

Khi bạn triển khai String() cho kiểu dữ liệu của mình, các hàm như fmt.Println sẽ tự động dùng hàm này để hiển thị giá trị của bạn:

type Person struct {
    Name string
    Age  int
}

func (p Person) String() string {
    return fmt.Sprintf("%s (%d years old)", p.Name, p.Age)
}

func main() {
    p := Person{Name: "Alice", Age: 30}
    fmt.Println(p)  // Alice (30 tuổi)
}

Giao diện error cũng đơn giản không kém, chỉ cần một phương thức Error() trả về một chuỗi:

type error interface {
    Error() string
}

Bất kỳ kiểu dữ liệu nào có phương thức Error() đều có thể dùng làm giá trị lỗi trong Go. Nhờ vậy, bạn có thể tạo các kiểu lỗi tùy chỉnh kèm thêm ngữ cảnh:

type ValidationError struct {
    Field   string
    Message string
}

func (e ValidationError) Error() string {
    return fmt.Sprintf("%s: %s", e.Field, e.Message)
}

func main() {
    err := ValidationError{Field: "email", Message: "invalid format"}
    fmt.Println(err)  // email: invalid format
}

Hai giao diện này thể hiện triết lý của Go: các giao diện nhỏ, tập trung, mở ra những hành vi mạnh mẽ thông qua việc triển khai ngầm.

challenge icon

Thử thách

Dễ

Hãy xây dựng một hệ thống theo dõi nhiệt độ sử dụng cả hai giao diện Stringer và error để hiển thị thông tin dễ đọc và xử lý lỗi rõ ràng.

Bạn sẽ tổ chức code trong hai tệp:

  • temperature.go: Tạo một struct Temperature có các trường Value (float64) và Unit (string). Triển khai phương thức String() để khi in ra, nhiệt độ được hiển thị theo định dạng dễ đọc. Đồng thời tạo một struct TemperatureError có các trường Temp (float64) và Reason (string), rồi triển khai phương thức Error() để cung cấp thông báo lỗi mô tả rõ ràng.
  • main.go: Tạo một hàm có tên ValidateTemperature nhận một Temperature và trả về lỗi nếu nhiệt độ không hợp lệ. Nhiệt độ không hợp lệ nếu thấp hơn độ không tuyệt đối (-273.15 đối với Celsius, -459.67 đối với Fahrenheit). Nếu hợp lệ, hàm trả về nil. Đọc dữ liệu nhiệt độ từ đầu vào, tạo một Temperature, kiểm tra tính hợp lệ rồi in kết quả phù hợp.

Đầu vào sẽ gồm:

  • Dòng 1: Giá trị nhiệt độ (số thực)
  • Dòng 2: Đơn vị (C cho Celsius hoặc F cho Fahrenheit)

Phương thức String() của bạn cần trả về định dạng:

[Value] degrees [Unit]

Trong đó, Unit là từ đầy đủ "Celsius" hoặc "Fahrenheit", tùy theo đầu vào.

Phương thức Error() của bạn cần trả về định dạng:

invalid temperature [Temp]: [Reason]

Nếu nhiệt độ hợp lệ, hãy in Temperature bằng fmt.Println (phương thức này sẽ sử dụng phương thức String() của bạn). Nếu nhiệt độ không hợp lệ, hãy in lỗi (phương thức này sẽ sử dụng phương thức Error() của bạn).

Ví dụ, với 25.5 và C, đầu ra sẽ là:

25.5 degrees Celsius

Với -500 và F, đầu ra sẽ là:

invalid temperature -500: below absolute zero

Dùng "below absolute zero" làm lý do khi nhiệt độ quá thấp.

Tự làm thử

package main

import (
	"fmt"
)

// ValidateTemperature kiểm tra nhiệt độ có hợp lệ không
// Trả về lỗi nếu nhiệt độ thấp hơn độ không tuyệt đối
// Độ không tuyệt đối: -273.15 theo thang Celsius, -459.67 theo thang Fahrenheit
func ValidateTemperature(t Temperature) error {
	// TODO: Triển khai logic kiểm tra tính hợp lệ
	// Kiểm tra nhiệt độ có thấp hơn độ không tuyệt đối theo đơn vị tương ứng không
	// Trả về TemperatureError nếu không hợp lệ, nil nếu hợp lệ
	return nil
}

func main() {
	var value float64
	var unit string
	fmt.Scanln(&value)
	fmt.Scanln(&unit)

	// TODO: Tạo struct Temperature với các giá trị đầu vào

	// TODO: Kiểm tra nhiệt độ bằng ValidateTemperature

	// TODO: Nếu có lỗi, in lỗi ra
	// Nếu không, in nhiệt độ ra (sử dụng phương thức String())
}
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch Go online