携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第14天,点击查看活动详情
方法
go没有类。不过你可以为结构体类型定义方法。方法就是一类带特殊的 接收者 参数的函数。方法接收者在它自己的参数列表内,位于func关键字和方法名之间。
package main
import (
"fmt"
"math"
)
type Vertex struct {
X, Y float64
}
func (v Vertex) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
func main() {
v := Vertex{3, 4}
fmt.Println((v).Abs())
}
方法即函数
方法只是个带接收者参数的函数。 可以和普通的函数对比下:
package main
import (
"fmt"
"math"
)
type Vertex struct {
X, Y float64
}
func Abs(v Vertex) float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
func main() {
v := Vertex{3, 4}
fmt.Println(Abs(v))
}
功能上没啥区别。
非结构体类型申明方法
你只能为同一包内定义的类型的接收者声明方法,而不能为其他包内定义的类型(包括int之类的内建类型)的接收者声明方法。
package main
import (
"fmt"
"math"
)
type MyFloat float64
func (f MyFloat) Abs() float64 {
if f < 0 {
return float64(-f)
}
return float64(f)
}
func main() {
f := MyFloat(-math.Sqrt2)
fmt.Println(f.Abs())
}
方法-指针接收者
你可以为指针接收者声明方法。这意味着对于某类型T,接收者的类型可以用*T的文法。
指针接收者的方法可以修改接收者指向的值。若使用值接收者,那么会对原始值的副本进行操作。
package main
import (
"fmt"
"math"
)
type Vertex1 struct {
X, Y float64
}
func (v Vertex1) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
func (v *Vertex1) Scale(f float64) {
v.X = v.X * f
v.Y = v.Y * f
}
func main() {
v := Vertex1{3, 4}
v.Scale(10)
fmt.Println(v.Abs())
}
其中v.Scale(10)本质上是(&v).Scale(10)相当于go的语法糖。
&表示取地址,*表示解析地址
改写成函数
把接收者移到方法入参列表内,实现功能一样。
package main
import (
"fmt"
"math"
)
type Vertex1 struct {
X, Y float64
}
func Abs(v Vertex1) float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
func Scale(v *Vertex1, f float64) {
v.X = v.X * f
v.Y = v.Y * f
}
func main() {
v := Vertex1{3, 4}
Scale(&v, 10)
fmt.Println(Abs(v))
}