Go语言学习笔记(六)-方法和接口
2017-03-30 14:45
671 查看
方法
Go中没有类,但是可以为结构体定义方法,方法就是一类带有特殊的接受者参数的函数。方法接受者在它自己的参数列表内,位于func关键字和方法名之间。例如:package main import "fmt" type Vertex struct{ x,y float64 } func (v Vertex) Abs() float64{ return math.Sqrt(v.X*v.X + v.Y*v.Y) } func main() { v := Vertex{3, 4} fmt.Println(v.Abs()) }
你也可以为非结构体类型声明方法。但只能为在同一包内定义的类型的接收者声明方法, 而不能为其它包内定义的类型(包括 int 之类的内建类型)的接收者声明方法。也就是说接收者的定义与方法的声明必须在同一包内,且不能为内建类型声明方法。
指针接收者
在Go中可以为指针接收者定义方法,对于某个类型T的接收者的类型可以使用*T文法(T不能是像*int之类的指针)。指针接收者的方法可以修改接收者指向的值。由于方法经常需要修改它的接收者,指针接收者比值接收者更常用。带指针参数的函数必须接受一个指针,而以指针为接收者的方法被调用时,接收者既能为值又能为指针。接受一个值作为参数的函数必须接受一个指定类型的值,而以值为接收者的方法被调用时,接收者既能为值又能为指针。
在开发中建议选择指针作为接收者,这样做有两个好处:
* 方法可以直接修改接收者的值
* 这样可以避免在每次调用方法时复制该值。若值的类型为大型结构体时,这样做会更加高效
接口
接口是由一组方法签名定义的集合,接口类型的值可以保存任何实现了接口方法的变量。类型通过实现了一个接口的所有方法来实现这个接口,而不需要专门的显示声明也就是”implements”关键字来声明。隐式接口从接口的实现中解耦了定义,这样接口的实现可以出现在任何包中,无需提前准备。在内部,接口的值可以看做是包含值和具体类型的元组:
( value , type )
接口的值保存了一个具体底层类型的具体值,接口值调用方法时会调用具体底层类型的同名方法。在Go中即使接口值的底层值是nil,方法仍然会被nil的接收者调用。
package main import "fmt" type I interface { M() } type T struct { S string } func (t *T) M() { if t == nil { fmt.Println("<nil>") return } fmt.Println(t.S) } func main() { var i I var t *T i = t describe(i) i.M() i = &T{"hello"} describe(i) i.M() } func describe(i I) { fmt.Printf("(%v, %T)\n", i, i) } //输出结果 //(<nil>, *main.T) //<nil> //(&{hello}, *main.T) //hello
而nil接口值不保存值也不保存具体类型。为nil接口调用方法会产生运行时错误,因为接口的元组内并未包含能够指明该调用哪个 具体 方法的类型。
指定了零个方法的接口被称为空接口,即:
interface{}
空接口可以保存任意类型的值,空接口一般是用来处理位置类型的值。
类型断言提供了访问接口值底层具体值的方法。
//断言i是T类型的值,并返回i的底层值返回给t t := i.(T) //断言i是V类型的值,若i是V类型的值ok的为true,v为i的底层值,否则ok为false,v为零值。 v,ok := i.(V)
以上就是接口断言的两种方式,第一种会触发warning提示,第二种则不会触发。因为第二种方式判断了i是否保存了T类型的值。
类型选择是一种按顺序从几个类型语言中选择分支的结构。与switch相似,不同的是类型选择中的case为类型。声明与类型断言相似,但是括号内由具体类型修改为type关键字。
package main import "fmt" func do(i interface{}) { switch v := i.(type) { case int: fmt.Printf("Twice %v is %v\n", v, v*2) case string: fmt.Printf("%q is %v bytes long\n", v, len(v)) default: fmt.Printf("I don't know about type %T!\n", v) } } func main() { do(21) do("hello") do(true) }
Stringer
fmt包中定义的Stringer是最普遍的接口之一。type Stringer interface { String() string}
Stringer是一个可以用字符串描述自己的类型。fmt包(还有很多包)都通过此接口来打印值,Stringer的功能有点类似于java中的toString。
相关文章推荐
- 9.笔记go语言——方法和接口
- go语言学习笔记---非入侵式接口设计探究
- Go语言学习笔记(五)方法
- GO语言学习-方法和接口
- go语言学习笔记-接口学习
- GO语言学习笔记3(函数接口并发)
- Go语言学习笔记---接口
- Go语言学习笔记 - 环境搭建
- JNI学习笔记(四)JNI中本地语言创建Java对象并且访问具体方法(附例子)
- Mcad学习笔记之异步编程(AsyncCallback委托,IAsyncResult接口,BeginInvoke方法,EndInvoke方法的使用小总结)
- go语言学习笔记之slice用法
- Go语言学习笔记--类型、指针、面向对象
- go语言学习笔记之并发编程
- Effective C# 学习笔记(二十三)理解接口方法和虚方法的区别
- Go语言学习笔记---通讯
- Go语言并发与并行学习笔记(一)
- Go语言学习笔记---函数
- 《JavaScript 语言精粹》 学习笔记 —— 第八章 方法
- Go语言学习笔记---包
- Go语言学习笔记4——struct