环境配置:
注意
本文假设你已经安装了Go并配置好相关环境,如果你还没有安装Go,请前往Go官方网站进行
下载安装💐 方法声明
在函数声明时,在其名字之前放上一个变量,即是一个方法。
第一个Distance的调用实际上用的是包级别的函数geometry.Distance,而第二个则是使用刚刚声明的Point,调用的是Point类下声明的Point.Distance方法。
这种p.Distance的表达式叫做选择器,因为他会选择合适的对应p这个对象的Distance方法来执行。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| package geometry
import "math"
type Point struct{ X, Y float64 }
// traditional function
func Distance(p, q Point) float64 {
return math.Hypot(q.X-p.X, q.Y-p.Y)
}
// same thing, but as a method of the Point type
func (p Point) Distance(q Point) float64 {
return math.Hypot(q.X-p.X, q.Y-p.Y)
}
p := Point{1, 2}
q := Point{4, 6}
fmt.Println(Distance(p, q)) // "5", function call
fmt.Println(p.Distance(q)) // "5", method call
|
🌸 基于指针对象的方法
当调用一个函数时,会对其每一个参数值进行拷贝。避免进行这种默认的拷贝,这种情况下我们就需要用到指针
1
2
3
4
| func (p *Point) ScaleBy(factor float64) {
p.X *= factor
p.Y *= factor
}
|
想要调用指针类型方法(*Point).ScaleBy,只要提供一个Point类型的指针即可,像下面这样。
1
2
3
| r := &Point{1, 2}
r.ScaleBy(2)
fmt.Println(*r) // "{2, 4}"
|
如果接收器p是一个Point类型的变量,并且其方法需要一个Point指针作为接收器,我们可以用下面这种简短的写法:
💮 封装
Go语言只有一种控制可见性的手段:大写首字母的标识符会从定义它们的包中被导出,小写字母的则不会。这种限制包内成员的方式同样适用于struct或者一个类型的方法。因而如果我们想要封装一个对象,我们必须将其定义为一个struct。
提前预留一部分空间,来避免反复的内存分配。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| type Buffer struct {
buf []byte
initial [64]byte
/* ... */
}
// Grow expands the buffer's capacity, if necessary,
// to guarantee space for another n bytes. [...]
func (b *Buffer) Grow(n int) {
if b.buf == nil {
b.buf = b.initial[:0] // use preallocated space initially
}
if len(b.buf)+n > cap(b.buf) {
buf := make([]byte, b.Len(), 2*cap(b.buf) + n)
copy(buf, b.buf)
b.buf = buf
}
}
|