A method is a function with a receiver associated with it. The syntax is func (receiver ReceiverType) MethodName() . You can have value receivers (func (r Receiver)) or pointer receivers (func (r *Receiver)). Value receivers work on a copy; pointer receivers can modify the original receiver.
Phương thức là một hàm có người nhận (receiver) được liên kết với nó. Cú pháp là func (receiver ReceiverType) MethodName() {}. Bạn có thể có người nhận giá trị (func (r Receiver)) hoặc người nhận con trỏ (func (r *Receiver)). Người nhận giá trị hoạt động trên một bản sao; người nhận con trỏ có thể sửa đổi người nhận gốc.
1package main23import "fmt"45type Rectangle struct {6 Width float647 Height float648}910// Method with value receiver — receives a copy11func (r Rectangle) Area() float64 {12 return r.Width * r.Height- Use value receiver when the method does not modify the receiver (most cases)
Dùng value receiver khi phương thức không cần sửa đổi người nhận (hầu hết các trường hợp)
- Use pointer receiver when the method must modify the receiver or when copying would be expensive (large structs)
Dùng pointer receiver khi phương thức cần sửa đổi người nhận hoặc khi bản sao sẽ tốn kém (struct lớn)
- Keep consistency: if any method of a type uses pointer receiver, consider making all methods use pointer receiver
Giữ nhất quán: nếu bất kỳ phương thức nào của type dùng pointer receiver, tất cả các phương thức khác cũng nên dùng pointer receiver
Go cho phép gọi phương thức con trỏ trên các giá trị — nó tự động lấy địa chỉ. Điều này giúp code gọn gàng hơn.
An interface in Go is a set of method signatures. Unlike some languages, you do not explicitly declare 'type X implements Interface Y'. Instead, any type that implements all the methods of an interface automatically satisfies the interface. This is called duck typing or implicit implementation.
Interface trong Go là một tập hợp các chữ ký phương thức. Không giống như các ngôn ngữ khác, không cần khai báo rõ ràng 'type X implements Interface Y'. Thay vào đó, bất kỳ kiểu nào triển khai tất cả các phương thức của interface đều tự động thỏa mãn interface. Đây gọi là duck typing hoặc implicit implementation.
1package main23import "fmt"45// Define an interface with two methods6type Shape interface {7 Area() float648 Perimeter() float649}1011type Rectangle struct {12 Width float64The empty interface interface (or alias any) has no methods, so every type satisfies it. It is used when you need to accept any type. To work with the value, you must use a type assertion: v.(Type) or v.(Type) with two return values (value, ok).
Interface trống interface{} (hay alias any) không có phương thức nào, vì vậy mọi kiểu đều thỏa mãn nó. Nó được dùng khi bạn cần chấp nhận bất kỳ kiểu nào. Để làm việc với giá trị, bạn phải dùng type assertion: v.(Type) hoặc v.(Type) có hai giá trị trả về (giá trị, ok).
1package main23import "fmt"45// Function that accepts any type6func printAny(x any) {7 fmt.Println(x)8}910// Type assertion with two return values (safer)11func checkType(x any) {12 val, ok := x.(string)Go provides several common interfaces in the standard library. Understanding them helps you write more compatible code.
Go cung cấp một số interface thông dụng trong thư viện chuẩn. Hiểu chúng giúp bạn viết code tương thích tốt hơn.
1package main23import (4 "fmt"5 "strings"6)78// error interface — any type with an Error() method can be an error9type error interface {10 Error() string11}12You can embed interfaces into other interfaces to create new interfaces from existing ones. For example, io.ReadWriter is a composition of io.Reader and io.Writer.
Bạn có thể nhúng interface vào interface khác để tạo interface mới từ các interface hiện có. Ví dụ, io.ReadWriter là thành phần của io.Reader và io.Writer.
1package main23import "fmt"45// Basic interfaces6type Reader interface {7 Read() string8}910type Writer interface {11 Write(data string)12}This is a core design principle of Go. Functions should accept interfaces (flexibility) but return concrete structs (simplicity). This lets callers easily use the result and makes code easier to test.
Đây là nguyên tắc thiết kế lõi của Go. Hàm nên chấp nhận interface (tính linh hoạt) nhưng trả về struct cụ thể (tính đơn giản). Điều này cho phép người gọi dễ dàng sử dụng kết quả và khiến code dễ dàng kiểm thử.
1package main23import "fmt"45// Writer interface6type Writer interface {7 Write(data string)8}910// Concrete struct to return11type Logger struct {12 name stringKey Takeaways
Điểm Chính
- Methods are functions with receivers; pointer receivers can modify the originalPhương thức là hàm có người nhận; người nhận con trỏ có thể sửa đổi gốc
- Interfaces are implicit — any type implementing all methods satisfies the interfaceInterface là ẩn — bất kỳ kiểu nào triển khai tất cả các phương thức đều thỏa mãn interface
- The empty interface any accepts any type; use type assertions to extract valuesInterface trống any chấp nhận bất kỳ kiểu nào; dùng type assertion để trích xuất giá trị
- Accept interfaces, return structs — this is the Go design principleChấp nhận interface, trả về struct — đây là nguyên tắc thiết kế Go
Practice
Test your understanding of this chapter
What is the main difference between a value receiver and a pointer receiver?
Sự khác biệt chính giữa value receiver và pointer receiver là gì?
In Go, do you need to explicitly declare that a type implements an interface?
Trong Go, bạn có cần khai báo rõ ràng rằng một kiểu triển khai một interface không?
The empty interface any can only hold primitive types like int, string, and float64.
Interface trống any chỉ có thể chứa các kiểu nguyên thủy như int, string và float64.
The principle 'Accept Interfaces, Return Structs' means your functions should accept concrete types and return interface types.
Nguyên tắc 'Chấp nhận Interface, Trả về Struct' có nghĩa là các hàm của bạn nên chấp nhận các kiểu cụ thể và trả về các kiểu interface.
Complete the interface implementation
Hoàn thành triển khai interface
type Comparable interface { Compare(other any) int } type Number struct { Value int } func (n Number) Compare(other any) int { if other_num, ok := other.(Number); ok { if n.Value > other_num.Value { return 1 } else if n.Value < other_num.Value { return -1 } return 0 } return -2 // error code } func checkComparison(a, b ) { fmt.Println(a.Compare(b)) }