结构体上的方法
值接收者与指针接收者的区别
结构体上的方法 是 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 反馈 — 无需本地设置。