Menu
CoddyTech

interface fmt.Stringer

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 75 trên 107.

Giao diện (interface) fmt.Stringer quyết định cách các kiểu dữ liệu của bạn hiển thị khi được in ra. Đây là một trong những giao diện được triển khai phổ biến nhất trong Go, được định nghĩa trong gói fmt:

type Stringer interface {
    String() string
}

Khi bạn truyền một giá trị vào fmt.Println, fmt.Printf với %v hoặc các hàm tương tự, Go sẽ kiểm tra xem kiểu đó có triển khai Stringer hay không. Nếu có, Go sẽ gọi phương thức String() để lấy biểu diễn dạng văn bản.

type Temperature struct {
    Celsius float64
}

func (t Temperature) String() string {
    return fmt.Sprintf("%.1f°C", t.Celsius)
}

func main() {
    temp := Temperature{Celsius: 23.5}
    fmt.Println(temp)  // 23.5°C
}

Nếu không có phương thức (method) String(), khi in ra sẽ hiển thị định dạng struct mặc định: {23.5}. Bằng cách triển khai Stringer, bạn kiểm soát chính xác cách kiểu dữ liệu của mình hiển thị.

Điều này đặc biệt hữu ích với những kiểu dữ liệu mà các giá trị trường thô không thể hiện rõ ý nghĩa. Kiểu Duration có thể hiển thị là "2h 30m" thay vì hiển thị số nano giây thô, hoặc kiểu User có thể hiển thị tên đã định dạng thay vì tất cả các trường của nó.

challenge icon

Thử thách

Dễ

Hãy xây dựng một hệ thống theo dõi thời gian, hiển thị thời lượng theo định dạng dễ hiểu! Bạn sẽ triển khai giao diện fmt.Stringer để kiểm soát cách các kiểu dữ liệu tùy chỉnh hiển thị khi in ra.

Bạn sẽ sắp xếp code trong hai tệp:

  • duration.go: Định nghĩa các kiểu dữ liệu liên quan đến thời gian với cách biểu diễn chuỗi tùy chỉnh.

    Tạo một cấu trúc Duration để lưu tổng số phút dưới dạng số nguyên. Triển khai phương thức String() để khi in ra, thời lượng hiển thị theo định dạng dễ đọc như 2h 30m cho 150 phút hoặc 0h 45m cho 45 phút. Luôn hiển thị cả giờ và phút.

    Tạo cấu trúc Task với các trường Name (chuỗi) và Time (Duration). Triển khai String() cho Task để hiển thị theo định dạng [Name]: [duration], trong đó thời lượng sử dụng phương thức String của chính nó.

  • main.go: Tạo và hiển thị các tác vụ cùng thời lượng của chúng.

    Đọc số lượng tác vụ, sau đó đọc tên và thời lượng tính bằng phút của từng tác vụ. Tạo các đối tượng Task và in trực tiếp từng đối tượng bằng fmt.Println: giao diện Stringer sẽ tự động định dạng.

    Sau khi in tất cả tác vụ, hãy tính và in tổng thời gian của tất cả tác vụ theo định dạng:

    Total: [duration]

Đầu vào sẽ có dạng:

  • Dòng 1: Số lượng tác vụ
  • Các dòng tiếp theo: Tên tác vụ và số phút (hai dòng cho mỗi tác vụ)

Ví dụ, với đầu vào:

3
Code Review
90
Meeting
45
Documentation
120

Đầu ra của bạn sẽ là:

Code Review: 1h 30m
Meeting: 0h 45m
Documentation: 2h 0m
Total: 4h 15m

Với đầu vào:

2
Design
180
Testing
65

Đầu ra của bạn sẽ là:

Design: 3h 0m
Testing: 1h 5m
Total: 4h 5m

Bằng cách triển khai Stringer, các kiểu dữ liệu của bạn tích hợp liền mạch với các hàm in ra của Go. Thay vì thấy các trường thô của cấu trúc như {90}, bạn sẽ nhận được đầu ra rõ nghĩa, dễ hiểu với người dùng.

Tự làm thử

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	reader := bufio.NewReader(os.Stdin)

	// Đọc số lượng tác vụ
	line, _ := reader.ReadString('\n')
	numTasks, _ := strconv.Atoi(strings.TrimSpace(line))

	// TODO: Tạo một slice để lưu các tác vụ
	// TODO: Theo dõi tổng số phút

	for i := 0; i < numTasks; i++ {
		// Đọc tên tác vụ
		name, _ := reader.ReadString('\n')
		name = strings.TrimSpace(name)

		// Đọc thời lượng tác vụ tính bằng phút
		minutesLine, _ := reader.ReadString('\n')
		minutes, _ := strconv.Atoi(strings.TrimSpace(minutesLine))

		// TODO: Tạo một Task với tên và Duration
		// TODO: In tác vụ ra (fmt.Println sẽ dùng giao diện Stringer)
		// TODO: Cộng minutes vào tổng
		_ = name
		_ = minutes
	}

	// TODO: In tổng thời lượng theo định dạng "Total: Xh Ym"
}
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