0Pricing
Go Academy · 课时

结构体上的方法

值接收者与指针接收者的区别

结构体上的方法 是 CoddyKit 上的免费 Go Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Go Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Go Academy 课程共包含 4 节课。

什么是方法

方法是带有接收者参数的函数。接收者位于 func 关键字和方法名之间,将函数绑定到某个类型。

值接收者

值接收者接收结构体的副本。当方法不需要修改状态时可以使用它:

package main
import "fmt"

type Circle struct{ Radius float64 }

func (c Circle) Area() float64 {
    return 3.14159 * c.Radius * c.Radius
}

func main() {
    c := Circle{Radius: 5}
    fmt.Printf("%.2f\n", c.Area()) // 78.54
}

指针接收者

指针接收者允许方法修改结构体。对于大型结构体来说效率更高:

package main
import "fmt"

type Counter struct{ N int }

func (c *Counter) Increment() { c.N++ }
func (c *Counter) Reset()     { c.N = 0 }

func main() {
    c := Counter{}
    c.Increment(); c.Increment()
    fmt.Println(c.N) // 2
    c.Reset()
    fmt.Println(c.N) // 0
}

何时使用指针接收者

在以下情况下使用指针接收者:

  • 方法需要修改接收者
  • 结构体较大(可以避免复制)
  • 保持一致性:如果有任何方法使用指针接收者,所有方法都应使用指针接收者

当结构体较小且方法只读取数据时,使用值接收者。

方法表达式与方法值

方法可以作为一等值使用:

package main
import "fmt"

type Adder struct{ Base int }

func (a Adder) Add(n int) int { return a.Base + n }

func main() {
    a := Adder{Base: 10}
    fn := a.Add          // method value — bound to a
    fmt.Println(fn(5))   // 15
}

非结构体类型的方法

您可以在同一包中的任何命名类型上定义方法,而不仅限于结构体:

package main
import "fmt"

type Celsius float64

func (c Celsius) ToFahrenheit() float64 {
    return float64(c)*9/5 + 32
}

func main() {
    t := Celsius(100)
    fmt.Println(t.ToFahrenheit()) // 212
}

自动解引用指针

调用方法时,Go 会自动获取地址或进行解引用。您不需要手动写出 (&c).Method():

package main
import "fmt"

type Box struct{ Val int }

func (b *Box) Double() { b.Val *= 2 }

func main() {
    b := Box{Val: 5}
    b.Double()           // Go auto-takes address
    fmt.Println(b.Val)   // 10
}

链式调用方法

返回接收者指针即可启用方法链(构建器模式):

package main
import "fmt"

type Builder struct{ result string }

func (b *Builder) Add(s string) *Builder {
    b.result += s
    return b
}
func (b *Builder) Build() string { return b.result }

func main() {
    s := (&Builder{}).Add("Hello").Add(", ").Add("World").Build()
    fmt.Println(s)
}

String 方法(fmt.Stringer)

实现 String() string 方法,以控制类型的打印方式:

package main
import "fmt"

type Point struct{ X, Y int }

func (p Point) String() string {
    return fmt.Sprintf("(%d, %d)", p.X, p.Y)
}

func main() {
    p := Point{3, 4}
    fmt.Println(p) // (3, 4)
}

nil 指针接收者

带有指针接收者的方法可以在 nil 指针上调用,这对于提供默认行为很有用:

package main
import "fmt"

type Node struct{ Val int }

func (n *Node) Value() int {
    if n == nil { return 0 }
    return n.Val
}

func main() {
    var n *Node
    fmt.Println(n.Value()) // 0
}

一致性原则

在 Go 标准库和惯用 Go 代码中,同一类型的所有方法都使用相同类型的接收者——全部使用指针接收者或全部使用值接收者。混用会导致接口出现细微错误。

快速检查

哪种接收者类型允许方法修改结构体的字段?

回顾:方法

要点:

  • 方法的接收者位于 func 和方法名之间
  • 值接收者:只读,适用于小型结构体
  • 指针接收者:用于修改、 large 结构体以及保持一致性
  • Go 会自动解引用,无需写出 (&v).Method()
  • 实现 String() string 以支持自定义打印

练习提示

定义一个带有 Balance float64 字段的 BankAccount 结构体。添加 Deposit 和 Withdraw 指针接收者方法,以及一个 String() 值接收者方法。

常见问题解答

「结构体上的方法」课时是免费的吗?

是的 — 「结构体上的方法」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Go Academy 课程的其余内容,请升级到 CoddyKit PRO。 Go Academy 课程共包含 4 节课。

「结构体上的方法」这节课中我会学到什么?

值接收者与指针接收者的区别 你通过在浏览器中直接运行的动手代码来练习 Go Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Go Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Go Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。

「结构体上的方法」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Go Academy 课中编写并运行代码吗?

能。每节 Go Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 定义和使用结构体
  2. 结构体上的方法
  3. 构造器模式
  4. 匿名结构体与组合
← 返回 Go Academy