Go指南笔记04_(方法和接口)

2018-01-13 10:53:07来源:https://juejin.im/post/5a5630f4f265da3e3d490b16作者:稀土掘金人点击

分享



Go指南


方法

Go 语言中没有类的概念,但是仍然可以在结构体类型上定义方法. 方法的接受者出现在 func 关键字和方法名之间的参数中.


func (v *T)name() T {}


事实上,我们可以对当前包中出现的任意类型定义任意方法,而不仅限于结构体.但是先决条件是当前包,不能对来自 其他包的类型或者基础类型 定义方法.


package main
import (
"fmt"
"math"
)
type MyFloat float64
func (f MyFloat) Abs() float64 {
if f < 0 {
return float64(-f)
}
return float64(f)
}
func main() {
f := MyFloat(-math.Sqrt2)
fmt.Println(f.Abs())
}

理解:上面的代码中,我们定义了MyFloat,MyFloat是64位的float类型,但是MyFloat并不是基本类型,所以我们可以对其定义方法


接收者位指针的方法

方法可以与命名类型或命名类型的指针相关联.我们使用指针类型的的原因有两个:1.避免在每个方法的调用中拷贝值.2.方法可以修改接收者指向的值.


package main
import (
"fmt"
"math"
)
type Vertex struct {
X, Y float64
}
func (v *Vertex) Scale(f float64) {
v.X = v.X * f
v.Y = v.Y * f
}
func (v *Vertex) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
func main() {
v := &Vertex{3, 4}
fmt.Printf("Before scaling: %+v, Abs: %v/n", v, v.Abs())
v.Scale(5)
fmt.Printf("After scaling: %+v, Abs: %v/n", v, v.Abs())
}
打印的结果:
Before scaling: {X:3 Y:4}, Abs: 5
After scaling: {X:15 Y:20}, Abs: 25
将Scale的接受者改为结构体变量v即: func (v Vertex) Scale(f float64) 打印的结果为:
Before scaling: &{X:3 Y:4}, Abs: 5
After scaling: &{X:3 Y:4}, Abs: 5

(未知对错,如有指教,不胜感激)理解:当接受者为指针的时候,我们可以直接通过指针指向的内存区域取值,这样就避免了每一次拷贝值,当不是指针的时候只是进行了值得拷贝然后执行函数中的计算,其实并没有改变结构体本身


接口

接口类型是有一组方法定义的集合,接口类型的值可以存放实现这些方法的任何值.是实现所有方法,而不是只实现一个即可.


package main
import (
"fmt"
"math"
)
type Abser interface {
Abs() float64
}
func main() {
var a Abser
f := MyFloat(-math.Sqrt2)
v := Vertex{3, 4}
a = f// a MyFloat 实现了 Abser
a = &v // a *Vertex 实现了 Abser
// 下面一行,v 是一个 Vertex(而不是 *Vertex)
// 所以没有实现 Abser。
a = v
fmt.Println(a.Abs())
}
type MyFloat float64
func (f MyFloat) Abs() float64 {
if f < 0 {
return float64(-f)
}
return float64(f)
}
type Vertex struct {
X, Y float64
}
func (v *Vertex) Abs() float64 {
return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

理解:代码中定义了一个接口类型Abser,同时MyFloat类型和Vertex的指针类型实现了Abser中定义的方法,所以可以使用接口类型Abser变量v调用其方法Abs(),而值类型v没有实现Abs()方法,所以其不满足Abser


隐式接口

类型通过实现接口中的方法来实现接口.没有显式声明的必要,所以也就没有implement关键字.


隐式接口解耦了实现接口的包和定义接口的包:互不依赖.


错误

Go程序使用error值来表示错误状态,其值不为nil的时候表示出现了错误.error类型是一个内建接口.


Readers

io包中制定了io.Readers接口,接口中的Read方法 func (T) Read(b []byte) (n int, err error) 可以实现用数据填充指定字节的slice,并且返回填充的字节数和错误信息,当遇到数据流结尾是,返回io.EOF错误.


package main
import (
"fmt"
"io"
"strings"
)
func main() {
r := strings.NewReader("Hello, Reader!")
b := make([]byte, 8)
for {
n, err := r.Read(b)
fmt.Printf("n = %v err = %v b = %v/n", n, err, b)
fmt.Printf("b[:n] = %q/n", b[:n])
if err == io.EOF {
break
}
}
}

上面代码以每次8字节的读取速度读取"Hello, Reader!"字符串,当返回的err错误信息为io.EOF的时候表征读取结束.


最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台