Phương thức trong Golang giống như hàm nhưng có một điểm khác biệt chính: chúng có đối số receiver, cho phép truy cập vào các thuộc tính của receiver. Receiver có thể là kiểu struct hoặc non-struct, nhưng cả hai phải nằm trong cùng một gói. Không thể tạo phương thức cho các kiểu được định nghĩa trong các gói khác, bao gồm các kiểu tích hợp như int hoặc string; nếu không, trình biên dịch sẽ báo lỗi.
Ví dụ:
package main
import "fmt"
// Định nghĩa một struct
type person struct {
name string
age int
}
// Định nghĩa một phương thức với struct receiver
func (p person) display() {
fmt.Println("Name:", p.name)
fmt.Println("Age:", p.age)
}
func main() {
// Tạo một phiên bản của struct
a := person{name: "a", age: 25}
// Gọi phương thức
a.display()
}
Kết quả:
Name: a
Age: 25
Cú pháp
func(receiver_name Type) method_name(parameter_list) (return_type) {
// Code
}
Receiver: Có thể được truy cập bằng phương thức này.
Phương thức với Receiver kiểu struct
Trong Go, bạn có thể định nghĩa một phương thức trong đó receiver có kiểu struct. Receiver có thể truy cập được bên trong phương thức. Ví dụ trước minh họa cách tiếp cận này với Receiver có kiểu struct.
Phương thức với Receiver không phải kiểu struct
Go cũng cho phép các phương thức có receiver không phải struct, miễn là kiểu của receiver và định nghĩa phương thức có trong cùng một gói. Bạn không thể định nghĩa một phương thức có kiểu receiver từ một gói khác (ví dụ: int, string).
Ví dụ:
package main
import "fmt"
// Tạo một kiểu tùy biến dựa trên int
type number int
// Định nghĩa một phương thức với receiver không phải struct
func (n number) square() number {
return n * n
}
func main() {
a := number(4)
b := a.square()
fmt.Println("Square of", a, "is", b)
}
Kết quả:
Square of 4 is 16
Phương thức với receiver pointer
Trong Go, các phương thức có thể có bộ nhận con trỏ. Điều này cho phép các thay đổi được thực hiện trong phương thức phản ánh trong trình gọi, điều này không thể thực hiện được với bộ nhận giá trị.
Cú pháp:
func (p *Type) method_name(...Type) Type { // Code}
Ví dụ:
package main
import "fmt"
// Defining a struct
type person struct {
name string
}
// Phương thức với receiver pointer để chỉnh sửa dữ liệu
func (p *person) changeName(newName string) {
p.name = newName
}
func main() {
a := person{name: "a"}
fmt.Println("Before:", a.name)
// Gọi phương thức này để thay đổi tên
a.changeName("b")
fmt.Println("After:", a.name)
}
Kết quả:
Before: a
After: b
Phương thức chấp nhận cả pointer và value
Không giống như hàm, phương thức Go có thể chấp nhận cả receiver giá trị và con trỏ. Bạn có thể truyền con trỏ hoặc giá trị và phương thức sẽ xử lý tương ứng.
Ví dụ:
package main
import "fmt"
type person struct {
name string
}
// Phương thức với receiver pointer
func (p *person) updateName(newName string) {
p.name = newName
}
// Phương thức với receiver value
func (p person) showName() {
fmt.Println("Name:", p.name)
}
func main() {
a := person{name: "a"}
// Gọi phương thức con trỏ cùng giá trị
a.updateName("b")
fmt.Println("After pointer method:", a.name)
// Gọi phương thức giá trị với con trỏ
(&a).showName()
}
Kết quả:
After pointer method: b
Name: b
Sự khác biệt giữa phương thức và hàm
Phương thức | Hàm |
Chứa một receiver | Không chứa receiver |
Có thể định nghĩa phương thức cùng tên nhưng khác kiểu | Không cho phép hàm cùng tên nhưng khác kiểu |
Không thể được dùng như đối tượng bậc nhất | Có thể được sử dụng như các đối tượng bậc nhất |