A Tour of Go 方法和接口阅读笔记

本文探讨Go语言中如何为结构体和非结构体声明方法,指针接收者与值接收者之间的区别,以及在接口实现和方法调用中的注意事项。强调指针接收者在方法调用时能修改值,而接口值即使为nil仍可调用方法。
摘要由CSDN通过智能技术生成

本文记录了我在学习Go指南的方法和接口小节的笔记。

  1. Go中没有类,但是可以为结构体类型和非结构体类型声明方法。在Go中,接收者的类型定义和方法声明必须在同一包内,不能为内建类型声明方法。
type Vertex struct {
	X, Y float64
}
func (v Vertex) Abs() float64 {
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
func (v *Vertex) Scale(f float64) {
	v.X = v.X * f
	v.Y = v.Y * f
}

type MyFloat float64
func (f MyFloat) Abs() float64 {
	if f < 0 {
		return float64(-f)
	}
	return float64(f)
}
  1. 指针接收者的方法可以修改接收者指向的值。由于方法经常需要修改它的接收者,指针接收者比值接收者更常用。使用指针接收者的好处有:方法能够修改其接收者指向的值;可以避免在每次调用方法时复制该值,若值的类型为大型结构体时,这样做会更加高效。
  2. 指针接收者的方法被调用时,接收者既能为值,又能为指针。值接收者的方法被调用时,接收者既能为值,又能为指针。对于指针接收者的方法Scale(),Go 会将语句 v.Scale(5) 解释为 (&v).Scale(5)。对于值接收者的方法Abs(),方法调用 p.Abs() 会被解释为 (*p).Abs()。(注:也就是说,在声明方法的时候需要注意是否要改变接收者的值,但是在使用的时候可以忽略方法的接收者是值还是指针)
var v Vertex
v.Scale(5)  // OK
p := &v
p.Scale(10) // OK
v.Abs(5)  // OK
p = &v
p.Abs(10)  // OK
  1. 在什么时候会区分值接收者和指针接收者呢?当接收者实现的方法为某个接口的方法的时候。
// 这里定义了一个接口,任何实现了Error()方法的类型都可以看作是这个接口。这时,如果实现Error()方法的为指针类型,则值类型的变量没有实现error接口。
type error interface {
    Error() string
}
func (e *MyError) Error() string {
	return fmt.Sprintf("at %v, %s",
		e.When, e.What)
}
func run() error {
	return &MyError{ // 这里要用指针
		time.Now(),
		"it didn't work",
	}
}
  1. 类型通过实现一个接口的所有方法来实现该接口。接口值可以用作函数的参数或返回值。在内部,接口值可以看做包含值和具体类型的元组:(value, type)。
  2. 即便接口内的具体值为 nil,方法仍然会被 nil 接收者调用。在一些语言中,这会触发一个空指针异常,但在 Go 中通常会写一些方法来优雅地处理它。
func (t *T) M() {
	if t == nil {
		fmt.Println("<nil>")
		return
	}
	fmt.Println(t.S)
}

如果for循环range的对象是切片,则 for i := range b{} 中i为index;如果b是有缓冲通道,则i为顺序从通道中取出的值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值