go学习(十七)go可以为任意类型定义方法!!

可以先看:go的数据类型
下面是针对不同类型,方法如何定义和使用。

1、方法定义

go可以为任意类型定义方法!!【指针类型除外】

方法比函数的好处:方法名可以简短。当我们在包外调用的时候这种好处就会被放大,因为我们可以使用这个短名字,而可以省略掉包的名字。

在函数声明时,在其名字之前放上一个变量,即是一个方法。这个附加的参数会将该函数附加到这种类型上,即相当于为这种类型定义了一个独占的方法。

(1)两种接收器声明方式:

接收器是类型对象

func (p Point) ScaleBy(factor float64) {xx}

接收器是类型指针对象
一般会约定如果Point这个类有一个指针作为接收器的方法,那么所有Point的方法都必须有一个指针接收器,即使是那些并不需要这个指针接收器的函数。

func (p *Point) ScaleBy(factor float64) {xx}

(2)指针类型的方法

go不能直接定义指针类型的方法!!!说的是下面这种情况,因为接收器放类型和指针都不对:

type intPoint *int
//func (?) addThree() int{
//  return 
//}
func main(){
  tmp := 10
  var b intPoint = &tmp
  // fmt.Print(b.addThree()) //指针类型的方法addThree没法定义,当然也就没法调用
}

但是,我们可以换个方式,用指针变量调用指针对应原类型的方法。调用方式有2种:

type myInt int
func (i myInt) addOne() myInt {
  return i + 1
}
func (i *myInt) addTwo() myInt {
  return *i + 2
}
func main(){
  //方式1
  var a myInt = 2 // a是myInt类型
  a.addOne() // a不变
  fmt.Println(a) // 2
  (&a).addTwo() //取地址即指针。传指针,a变
  fmt.Println(a) // 4

  //方式2
  b := new(myInt) // b是*myInt类型,指针
  *b = 10
  // 传值,b不变
  (*b).addOne() // 正常访问,传入myInt类型
  fmt.Println(*b)
  b.addOne() // go自己处理,传入*myInt自动转为myInt类型
  fmt.Println("b:", *b)
  //下面传入指针,b会变
  b.addTwo() // 正常访问,传入*myInt类型。
  fmt.Println(*b)
  (*b).addTwo() // go自己处理,传入myInt自动转为*myInt类型
  fmt.Println(*b)
}

(3)

如果命名类型T(译注:用type xxx定义的类型)的所有方法都是用T类型自己来做接收器(而不是*T),那么拷贝这种类型的实例就是安全的;调用他的任何一个方法也就会产生一个值的拷贝。比如time.Duration的这个类型,在调用其方法时就会被全部拷贝一份,包括在作为参数传入函数的时候。

但是如果一个方法使用指针作为接收器,你需要避免对其进行拷贝,因为这样可能会破坏掉该类型内部的不变性。比如你对bytes.Buffer对象进行了拷贝,那么可能会引起原始对象和拷贝对象只是别名而已,实际上它们指向的对象是一样的。紧接着对拷贝后的变量进行修改可能会有让你有意外的结果。

译注: 作者这里说的比较绕,其实有两点:

1 不管你的method的receiver是指针类型还是非指针类型,都是可以通过指针/非指针类型进行调用的,编译器会帮你做类型转换。
2 在声明一个method的receiver该是指针还是非指针类型时,你需要考虑两方面的因素,第一方面是这个对象本身是不是特别大,如果声明为非指针变量时,调用会产生一次拷贝;第二方面是如果你用指针类型作为receiver,那么你一定要注意,这种指针类型指向的始终是一块内存地址,就算你对其进行了拷贝。熟悉C或者C++的人这里应该很快能明白。//没懂

参考:
https://blog.csdn.net/u013862108/article/details/105028124
https://docs.hacknode.org/gopl-zh/ch6/ch6-02.html

2、实现接口的表示:接收器不能是指针!!

接收参数person不可以是指针类型,否则不认为是实现了接口

参考:
https://www.cnblogs.com/craneboos/p/8615476.html

上一篇:go默认是值传递,可以通过传入指针变成引用传递


下一篇:P1421 小玉买文具