Menu
CoddyTech

Receiver con trỏ

Thuộc phần Logic và luồng điều khiển trong hành trình GO của Coddy. Bài học 8 trên 68.

Receiver giá trị hoạt động với bản sao của struct, còn receiver con trỏ hoạt động trực tiếp với instance struct ban đầu. Khi định nghĩa một phương thức với receiver con trỏ, phương thức có thể sửa đổi dữ liệu ban đầu vì nó nhận một con trỏ đến struct thay vì một bản sao.

Để tạo một receiver con trỏ, bạn thêm dấu hoa thị * trước tên kiểu trong phần khai báo receiver:

type Person struct {
    Name string
    Age  int
}

func (p *Person) haveBirthday() {
    p.Age++  // Thao tác này thay đổi struct gốc
}

Trong ví dụ này, (p *Person) là receiver con trỏ. Khi bạn gọi phương thức haveBirthday trên một instance Person, phương thức nhận một con trỏ đến struct ban đầu. Mọi thay đổi đối với các trường của struct thông qua con trỏ này sẽ sửa đổi dữ liệu ban đầu vĩnh viễn.

Receiver con trỏ rất cần thiết khi các phương thức của bạn cần cập nhật những trường của struct, nên chúng rất phù hợp với các thao tác làm thay đổi trạng thái dữ liệu.

challenge icon

Thử thách

Dễ

Trong thử thách này, bạn sẽ luyện tập tạo phương thức với bộ nhận con trỏ bằng cách xây dựng một hệ thống tài khoản ngân hàng đơn giản. Bạn sẽ tạo một struct Account và định nghĩa các phương thức có thể thay đổi số dư tài khoản bằng bộ nhận con trỏ.

Bạn sẽ nhận được ba đầu vào:

  • Một chuỗi biểu thị tên chủ tài khoản (ví dụ: "John Smith")
  • Một chuỗi biểu thị số dư ban đầu của tài khoản (ví dụ: "1000.50")
  • Một chuỗi biểu thị số tiền giao dịch (ví dụ: "250.75")

Nhiệm vụ của bạn là:

  1. Định nghĩa một struct Account có hai trường: Name (chuỗi) và Balance (float64)
  2. Tạo một phương thức có tên deposit với bộ nhận con trỏ, cộng số tiền đã cho vào số dư tài khoản
  3. Tạo một phương thức có tên withdraw với bộ nhận con trỏ, trừ số tiền đã cho khỏi số dư tài khoản
  4. Tạo một phương thức có tên displayBalance với bộ nhận giá trị, in thông tin tài khoản theo định dạng: "Account: [name], Balance: $[balance]"
  5. Phân tích cú pháp các đầu vào để tạo một instance Account
  6. Gọi displayBalance để hiển thị số dư ban đầu
  7. Gọi deposit với số tiền giao dịch
  8. Gọi displayBalance để hiển thị số dư sau khi nạp tiền
  9. Gọi withdraw với số tiền giao dịch
  10. Gọi displayBalance để hiển thị số dư cuối cùng

Số dư cần được hiển thị với độ chính xác đến hai chữ số thập phân. Thử thách này minh họa cách bộ nhận con trỏ cho phép phương thức thay đổi dữ liệu của struct gốc, khác với bộ nhận giá trị, vốn hoạt động trên các bản sao.

Tự làm thử

package main

import (
	"fmt"
	"strconv"
)

// TODO: Định nghĩa struct Account tại đây

// TODO: Định nghĩa phương thức (method) deposit với receiver dạng con trỏ tại đây

// TODO: Định nghĩa phương thức withdraw với receiver dạng con trỏ tại đây

// TODO: Định nghĩa phương thức displayBalance với receiver dạng giá trị tại đây

func main() {
	// Đọc đầu vào
	var name string
	var initialBalanceStr string
	var transactionAmountStr string
	
	fmt.Scanln(&name)
	fmt.Scanln(&initialBalanceStr)
	fmt.Scanln(&transactionAmountStr)
	
	// Chuyển các chuỗi đầu vào sang kiểu dữ liệu phù hợp
	initialBalance, _ := strconv.ParseFloat(initialBalanceStr, 64)
	transactionAmount, _ := strconv.ParseFloat(transactionAmountStr, 64)
	
	// TODO: Tạo một instance của Account
	
	// TODO: Hiển thị số dư ban đầu, nạp tiền, hiển thị số dư, rút tiền, hiển thị số dư cuối cùng
}
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 Logic và luồng điều khiển

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