«

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 和通道来实现并发编程。

}