Menu
CoddyTech

Hàm new()

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

Go cung cấp một hàm tích hợp có tên new(), hàm này cấp phát bộ nhớ cho một kiểu dữ liệu và trả về con trỏ đến kiểu đó. Bộ nhớ được cấp phát sẽ được khởi tạo bằng giá trị không của kiểu dữ liệu đó.

p := new(int)      // Cấp phát bộ nhớ cho một số nguyên (integer)
fmt.Println(*p)    // 0 (giá trị không)
fmt.Println(p)     // 0xc000018030 (địa chỉ bộ nhớ)

Hàm (function) new() nhận một kiểu dữ liệu làm đối số và trả về con trỏ đến một giá trị zero mới được cấp phát thuộc kiểu đó. Điều này đặc biệt hữu ích khi bạn cần một con trỏ nhưng không có biến nào sẵn để tham chiếu.

Với struct, new() tạo một con trỏ đến struct với tất cả trường được đặt thành giá trị không.

type Person struct {
    Name string
    Age  int
}

p := new(Person)
fmt.Println(p.Name)  // "" (chuỗi rỗng)
fmt.Println(p.Age)   // 0

Có thể bạn đang băn khoăn khi nào nên dùng new() thay vì toán tử địa chỉ &. Hai cách dưới đây tương đương nhau:

// Dùng new()
p1 := new(Person)

// Dùng toán tử lấy địa chỉ với giá trị trực tiếp
p2 := &Person{}

Cú pháp (syntax) &Person{} phổ biến hơn trong thực tế vì cho phép bạn khởi tạo các trường cùng lúc. Dùng new() khi bạn muốn tạo một instance có giá trị bằng không và ưu tiên ngữ nghĩa cấp phát bộ nhớ tường minh.

challenge icon

Thử thách

Dễ

Hãy xây dựng một trình quản lý cấu hình để minh họa cách new() cấp phát bộ nhớ và khởi tạo các struct về giá trị 0. Bạn sẽ thấy cách làm này khác với việc dùng toán tử lấy địa chỉ cùng một struct literal như thế nào.

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

  • config.go: Định nghĩa một struct ServerConfig với các trường Host (string), Port (int), MaxConnections (int) và DebugMode (bool). Tạo hai hàm:
    • NewServerConfig dùng new() để cấp phát một ServerConfig rồi trả về trực tiếp con trỏ (với tất cả giá trị 0)
    • ConfigureServer nhận một con trỏ *ServerConfig cùng với chuỗi host và số nguyên port, sau đó dùng con trỏ để đặt các trường đó trong cấu hình
    Đồng thời thêm phương thức Display trên *ServerConfig để trả về một chuỗi đã định dạng, hiển thị tất cả giá trị cấu hình.
  • main.go: Đọc host và port từ đầu vào. Trước tiên, tạo một cấu hình bằng NewServerConfig() rồi hiển thị cấu hình để cho thấy các giá trị 0. Sau đó dùng ConfigureServer để đặt host và port, rồi hiển thị lại cấu hình để cho thấy các giá trị đã cập nhật.

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

  • Dòng 1: Tên host (string)
  • Dòng 2: Số port (số nguyên)

Phương thức Display của bạn cần trả về một chuỗi theo đúng định dạng này:

Host: [Host]
Port: [Port]
MaxConnections: [MaxConnections]
DebugMode: [DebugMode]

In kết quả hiển thị hai lần, một lần trước khi cấu hình (cho thấy các giá trị 0) và một lần sau khi cấu hình (cho thấy host và port đã cập nhật).

Ví dụ, với localhost và 8080, kết quả của bạn sẽ là:

Host: 
Port: 0
MaxConnections: 0
DebugMode: false
Host: localhost
Port: 8080
MaxConnections: 0
DebugMode: false

Lưu ý rằng lần hiển thị đầu tiên cho thấy tất cả giá trị 0 (chuỗi rỗng, 0, 0, false) vì new() khởi tạo mọi thứ về giá trị 0. Sau khi gọi ConfigureServer, chỉ host và port thay đổi, còn các trường khác vẫn giữ giá trị 0.

Tự làm thử

package main

import (
	"fmt"
)

func main() {
	// Đọc đầu vào
	var host string
	var port int
	fmt.Scanln(&host)
	fmt.Scanln(&port)

	// TODO: Tạo cấu hình bằng NewServerConfig() và hiển thị cấu hình đó
	// Thao tác này sẽ hiển thị các giá trị mặc định

	// TODO: Dùng ConfigureServer để đặt host và port

	// TODO: Hiển thị lại cấu hình để xem các giá trị đã cập nhật
}
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