go方法变量和方法表达式

在本篇浅说一下go的方法变量和方法表达式,大家通常所说的方法变量就是struct实例获取方法对象,而方法表达式是struct类型获取方法对象, 需要传递struct实例对象作为参数。现在看这个也许会云里雾里,但可以通过举例来理清思路,下面就开始举例~

第一弹:方法变量

type Point struct{ X, Y float64 }

// Point类型的声明
func (p Point) Distance(q Point) float64 {
	return math.Hypot(q.X-p.X, q.Y-p.Y)
}

// 这个方法的接收者是指针接收者,注意指针接收者和指针类型接收者的区别
func (p *Point) ScaleBy(factor float64) {
	p.X *= factor
	p.Y *= factor
}
	p := Point{1, 2}
	q := Point{4, 6}

	distanceFromP := p.Distance        // 方法变量
	fmt.Println(distanceFromP(q))      // "5"
	var origin Point                   // {0, 0}
	fmt.Println(distanceFromP(origin)) // "2.23606797749979", 根号5

	scaleP := p.ScaleBy // 方法变量
	scaleP(2)           // p 变成 (2, 4)
	scaleP(3)           // 然后是 (6, 12)
	scaleP(10)          // 然后是 (60, 120)

p.Distance可以赋予一个方法变量,它是一个函数。这个函数只需要提供实参而不需要提供接收者就能够调用。

在一个包的API需要一个函数值、且调用方希望操作的是某一个绑定了对象的方法的话,方法变量会非常实用。举例来说,下面例子中的time.AfterFunc这个函数的功能是在指定的延迟时间之后来执行一个另外的函数。且这个函数操作的是一个Rocket对象r

type Rocket struct { /* ... */ }
func (r *Rocket) Launch() { /* ... */ }
r := new(Rocket)
time.AfterFunc(10 * time.Second, func() { r.Launch() })

直接用方法变量传入AfterFunc的话可以更为简短:

time.AfterFunc(10 * time.Second, r.Launch)

第二弹:方法表达式

distance := Point.Distance   // 方法表达式
fmt.Println(distance(p, q))  // "5"
fmt.Printf("%T\n", distance) // "func(Point, Point) float64"

scale := (*Point).ScaleBy
scale(&p, 2)
fmt.Println(p)            // "{2 4}"
fmt.Printf("%T\n", scale) // "func(*Point, float64)"

方法表达式携程写成T.f或者(*T).f,其中T是类型,方法表达式是一种函数变量,其第一个形参为原方法的接收者。

当需要用一个变量来代表多个方法中的一个,而方法都属于同一个类型时,方法变量可以帮助你调用这个值对应的方法来处理。

type Point struct{ X, Y float64 }

func (p Point) Add(q Point) Point { return Point{p.X + q.X, p.Y + q.Y} }
func (p Point) Sub(q Point) Point { return Point{p.X - q.X, p.Y - q.Y} }

type Path []Point

func (path Path) TranslateBy(offset Point, add bool) {
    var op func(p, q Point) Point
    if add {
        op = Point.Add
    } else {
        op = Point.Sub
    }
    for i := range path {
        // 调用 path[i].Add(offset)或者path[i].Sub(offset).
        path[i] = op(path[i], offset)
    }
}

本文参考《go程序设计语言》

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值