格式: func (receiver) methodName(varName type,) returnType{}
大写方法为public,小写为private
type Point struct{x,y float64}
//普通的函数
func Distance(p,q Point) float64{
return math.Hypot(p.x - q.x,p.y - q.y)
}
//接受器为Point类型的函数
func (p Point) Distance1(q Point) float64{
return math.Hypot(p.x - q.x,p.y - q.y)
}
//接受器为*Point类型的函数
func (p *Point) Distance2(q Point) float64{
return math.Hypot(p.x - q.x,p.y - q.y)
}
接受器为Point类型的函数在调用的时候,是值拷贝
*Point类型则是引用传递,相当于拷贝引用
类型的函数编写约定:
如果任意一个函数需要使用指针类型作为接收器参数,那么其他的所有函数都需要使用这样的方式。当然游客可以打破这个约定。
pp := &Point{1,2}
pp2 := &Point{2,4}
pp.Distance1(*pp2)
调用接受器参数是Point的方法,隐式地执行了*pp
pp := Point{1,2}
pp2 := Point{2,4}
pp2.Distance2(pp)
调用接受器参数是*Point的方法,隐式地执行了&pp2
Point{1,2}.Distance(Point{2,4})
pp := &Point{1,2}
pp.Distance2(Point{2,4})
以上代码表示的是,调用者类型和函数接收器类型是一致的,这种情况就不用转换了。
从具体类型例如Point 转换成 指针类型 *Point (&p)
条件:变量,例如struct类型的变量,数组或者是切片元素。
Point{1,2}.Distance2(Point{2,4})//编译错误,不能获取Point的地址
从指针类型 *Point
转换成 具体类型例如Point (*p
)
条件:函数调用者是可寻址的,即从地址可以得到具体的值
pp := &Point{1,2}
pp.Distance1(Point{2,4})
(*pp).Distance1(Point{2,4})//两者是等同的
可以在切片上定义函数
还有其他的类型也可以,比如strings,map,只要是其基本类型是指针或者接口
type Path []Point
func (path Path) Distance() float64 {
sum := 0.0
for i := range path {
if i > 0 {
sum += path[i-1].Distance(path[i])
}
}
return sum
}
func testFunc(){
path := Path{
{1,1},{5,1},{5,4},{1,1},
}
fmt.Println(path.Distance())//12
}