Golang 方法
时间:2025-1-10 14:12 作者:杨佳乐 分类: Golang
package main
import "fmt"
// 方法
// 方法 是一种与特定类型关联的函数。
// 它与函数的不同之处在于,方法绑定到某个类型上,可以通过该类型的实例调用。
// Go 中的函数和方法在语法上非常相似,区别主要在于方法有一个接收者(Receiver),它指定了该方法属于哪个类型
//基本定义
//在 Go 中,方法是与类型关联的函数。方法的定义与函数类似,但方法定义需要指定一个 接收者,接收者是方法的“主人”,即该方法操作的类型实例
// func (receiver variable) MethodName(parameters) returnType {
// // 方法体
// }
// receiver:接收者,表示方法绑定的类型。它类似于其他语言中的 this 或 self,但在 Go 中,接收者是显式的,在方法定义时直接指定。
// MethodName:方法名。
// parameters:参数列表,和普通函数一样。
// returnType:返回类型(可以没有)。
// 定义一个结构体类型
type Rectangle struct {
Width, Height int
}
// 定义一个方法,计算矩形的面积
func (r Rectangle) Area() int {
return r.Width * r.Height
}
// 引用接收者方法
func (r *Rectangle) SetWidth(width int) {
r.Width = width // 修改原对象
}
func main(){
tr := Rectangle{
Width:5,
Height:10,
}
// 调用结构体的Area方法
fmt.Println(tr.Area())
// 值接收者 vs 引用接收者
// 值接收者
// 值接收者意味着方法接收的是该类型的副本(拷贝)。这种方式会复制接收者对象,因此对于大型对象,可能会带来性能损失。
// 用值接收者定义的方法不能修改接收者的值。
// 例如下面这种方法,无法修改原始Rectangle的Width,因为接收者是值类型
// func (r Rectangle) SetWidth(width int) {
// r.Width = width
// }
// 引用接收者
//引用接收者意味着方法接收的是该类型的指针,可以修改接收者的值。通常情况下,使用引用接收者可以提高性能,避免不必要的拷贝,尤其是当接收者是大型结构体时。
//使用指针接收者的方法可以修改接收者实例的字段。
// 这样,SetWidth 方法就能修改原始的 Rectangle 实例,因为接收者是指针类型。
// func (r *Rectangle) SetWidth(width int) {
// r.Width = width
// }
//引用接收方法,可以修改tr的值
tr.SetWidth(30)
fmt.Println(tr)
// 方法的传递方式
// Go 方法有两个主要传递方式:值传递 和 指针传递。在方法定义时,选择值接收者还是指针接收者,决定了传递方式。
// 值接收者:每次调用方法时,都会传递该类型的副本(拷贝),适用于方法不修改接收者的情况。
// 指针接收者:每次调用方法时,都会传递该类型的指针,适用于方法可能修改接收者的情况,且能避免拷贝开销。
// 方法与接口
// 在 Go 中,方法是与接口的实现紧密相关的。一个类型如果实现了接口中的所有方法,则该类型就实现了该接口,而不需要显式声明。Go 的接口是隐式实现的
// 示例
// // 定义一个接口
// type Shape interface {
// Area() int
// }
// // 定义一个结构体
// type Rectangle struct {
// Width, Height int
// }
// // 实现 Shape 接口的 Area 方法
// func (r Rectangle) Area() int {
// return r.Width * r.Height
// }
// func main() {
// var s Shape
// rect := Rectangle{Width: 5, Height: 4}
// s = rect // rect 实现了 Shape 接口
// fmt.Println("Area of Shape:", s.Area()) // 输出: Area of Shape: 20
// }
// 方法与匿名字段(嵌入式结构体)
// Go 允许通过匿名字段(embedding)实现方法的继承。通过将一个结构体嵌入到另一个结构体中,嵌入的结构体的方法可以被外部结构体调用
//示例
// 定义一个基础结构体
// type Shape struct {
// Width, Height int
// }
// func (s Shape) Area() int {
// return s.Width * s.Height
// }
// // 定义一个继承 Shape 的结构体
// type Rectangle struct {
// Shape // 匿名字段,继承了Shape的方法
// }
// func main() {
// rect := Rectangle{Shape: Shape{Width: 5, Height: 4}}
// fmt.Println("Area of Rectangle:", rect.Area()) // 输出: Area of Rectangle: 20
// }
// 在这个例子中,Rectangle 嵌入了 Shape 结构体,从而继承了 Shape 的 Area 方法。这样可以避免重复实现相同的方法
// 方法的组合与封装
//方法也可以作为组合的一部分来封装其他类型的行为。这种方式通常用于实现更复杂的类型,封装细节,暴露公共接口
// 示例
// 定义一个基础类型
// type Circle struct {
// Radius int
// }
// func (c Circle) Area() int {
// return 3 * c.Radius * c.Radius
// }
// // 定义一个更复杂的类型,组合了 Circle
// type ColoredCircle struct {
// Circle // 组合 Circle
// Color string
// }
// func main() {
// coloredCircle := ColoredCircle{
// Circle: Circle{Radius: 5},
// Color: "Red",
// }
// fmt.Println("Area of Colored Circle:", coloredCircle.Area()) // 输出: Area of Colored Circle: 75
// fmt.Println("Color:", coloredCircle.Color) // 输出: Color: Red
// }
// 方法与 Goroutine
// Go 中的并发编程依赖于 goroutine 和通道,方法也可以用来在 goroutine 中执行某些操作。
// type Counter struct {
// Count int
// }
// // 方法:计数
// func (c *Counter) Increment() {
// c.Count++
// }
// // 启动多个 goroutine
// func main() {
// counter := Counter{Count: 0}
// for i := 0; i < 5; i++ {
// go func() {
// counter.Increment()
// }()
// }
// // 等待 goroutines 完成
// time.Sleep(time.Second)
// fmt.Println("Counter value:", counter.Count) // 输出:Counter value: 5
// }
//总结
// Go 中的方法与函数非常相似,但有一个关键区别:方法与特定类型(例如结构体)绑定。理解 Go 方法的以下特性对于编写高效且易于维护的 Go 代码至关重要
// 接收者:方法需要一个接收者,接收者决定了方法属于哪个类型。
// 值接收者与指针接收者:方法可以使用值接收者或指针接收者,选择哪种接收者取决于是否需要修改接收者的数据。
// 方法与接口:Go 中的方法与接口息息相关,类型实现接口不需要显式声明,只要方法匹配即可。
// 嵌入式结构体:通过嵌入其他结构体,可以轻松实现代码复用和组合。
// 方法与并发:方法可以结合 goroutine 和通道来实现并发编程。
}