接口
<h1>单元目标</h1>
<ul>
<li>使用接口来实现多态</li>
</ul>
<h1>接口</h1>
<p><img src="https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/6/20/172cff30b3bf3900~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp" alt="" /></p>
<p><img src="https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/6/20/172d09e478c2d659~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp" alt="" /></p>
<h3>3,使用接口来实现多态</h3>
<p>接口的意义是对其他类型的一个概括,接口内可以定义很多个方法,谁将这些方法实现,就可以认为是实现了该接口。Go语言的多态,主要是通过接口来实现。</p>
<p><img src="https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/6/20/172cff886f91b5de~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp" alt="" /></p>
<pre><code>package main
import (
"fmt"
)
func main() {
h := Haojiahuo{name: "好家伙"}
fmt.Println(h.name)
l := Laolitou{name: "老李头"}
fmt.Println(l.name)
//testInterface 需要参数类型为Kongfu接口类型的参数
//h实现了Kongfu接口的方法
//h就是这个接口的实现 就可以作为这个函数的参数
testInterface(h)
var kf Kongfu
kf = h
kf.Toad()
l.PlayGame()
}
//测试方法
func testInterface(k Kongfu) {
k.Toad()
k.SixSwords()
}
//定义接口
type Kongfu interface {
Toad() //蛤蟆功
SixSwords() //六脉神剑
}
//实现类
type Haojiahuo struct {
name string
}
//实现类
type Laolitou struct {
name string
}
//实现方法
func (o Haojiahuo) Toad() {
fmt.Println(o.name, "实现了蛤蟆功..")
}
//实现方法
func (o Haojiahuo) SixSwords() {
fmt.Println(o.name, "实现了六脉神剑..")
}
//实现方法
func (f Laolitou) Toad() {
fmt.Println(f.name, "也实现了蛤蟆功..")
}
//实现方法
func (f Laolitou) SixSwords() {
fmt.Println(f.name, "也实现了六脉神剑.")
}
//实现自己的方法
func (f Laolitou) PlayGame() {
fmt.Println(f.name, "玩游戏..")
}</code></pre>
<p><img src="https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/6/20/172d0a7be4a75605~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp" alt="" /></p>
<p>使用接口对方法进行约束,然后让方法实现接口,这样规范了方法。通过使用同样的接口名称,但是在调用的时候使用不同的类,实现执行不同的方法。这样就实现了Go语言中的多态。</p>
<h2>空接口</h2>
<p>空接口就是不包含任何方法的接口,所有的类型都可以实现空接口,因此空接口可以实现存储任意类型的数据, 谁实现它就被看作是谁的实现类。</p>
<pre><code>package main
import (
"fmt"
)
func main() {
Test1(0)//使用int类型做为参数传入到函数
Test1("ceshi")//使用string类型做为参数传入到函数
}
//空接口
type T interface {
}
//定义一个函数 接收Test接口类型的数据
func Test1(t T) {
fmt.Println(t)
}</code></pre>
<p><img src="https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/6/20/172d0bf93699c9bd~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp" alt="" /></p>
<p>可以将空接口类型写为<code>interface{}</code> 这种类型可以理解为任何类型。类似其他语言中的<code>object</code>。</p>
<h2>空接口的使用</h2>
<p>空接口既然可以传任意类型,利用这个特性可以把空接口interface{}当做容器使用。</p>
<pre><code>func Test() {
//创建一个map类型 key为string val为空接口,这样值就可以存储任意类型了
m := make(map[string]interface{})
m["a"] = "zhangsan"
m["b"] = 1.1
m["c"] = true
fmt.Println(m)
}
package main
import "fmt"
// 字典结构
type Dictionary struct {
data map[string]interface{} // 数据key为string值为interface{}类型
}
// 获取值
func (d *Dictionary) GetData(key string) interface{} {
return d.data[key]
}
// 设置值
func (d *Dictionary) SetData(key string, value interface{}) {
d.data[key] = value
}
// 创建一个字典
func NewDict() *Dictionary {
return &Dictionary{
data: make(map[string]interface{}),//map类型使用前需要初始化,所以需要使用make创建 防止空指针异常。
}
}
func main() {
// 创建字典实例
dict := NewDict()
// 添加数据
dict.SetData("001", "第一条数据")
dict.SetData("002", 3.1415)
dict.SetData("003", false)
// 获取值
d := dict.GetData("001")
fmt.Println(d)
}</code></pre>
<h2>Go语言中的错误</h2>
<p>错误和异常不同,错误是在程序中正常存在的,可以预知的失败在意料之中。而异常通常指在不应该出现问题的地方出现问题,比如空指针,这在人们的意料之外。go语言没有 <code>try......catch</code> 这样的方式来捕获异常所以Go定义属于自己的一种错误类型,用error表示错误。</p>
<p><img src="https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/6/20/172d0d5af5ad8444~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp" alt="" /></p>
<p>例如:我们在读取一个不存在的文件时候。如果文件正常存在就返回文件的内容,否则就返回一个err信息。</p>
<pre><code>package main
import (
"fmt"
"io/ioutil"
)
func main() {
//使用io/ioutil包下的读取文件方法
conent, err := ioutil.ReadFile("test.txt")
if err != nil {
fmt.Println(err)//打印错误信息
} else {
fmt.Println(string(conent))//返回正常信息
}
}</code></pre>
<p>通常情况一个函数如果有错误,都会在返回值最后一个,返回一个error类型的错误,根据这个值来判断是否是非nil的值,如果是nil表示没有错误,如果nil不为空,则需要进行错误处理。</p>
<p>error的定义是一个接口,接口内部包含一个返回字符串类型的方法Error()</p>
<pre><code>type error interface {
Error() string
}</code></pre>
<p>知道了error的定义是一个接口类型,那么只要实现了这个接口 都可以用来处理错误信息。来返回一个错误提示给用户。Go语言也提供了一个内置包errors ,来创建一个错误对象。</p>
<p><img src="https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/6/20/172d2486f5285d9b~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp" alt="" /></p>
<pre><code>package main
import (
"errors"
"fmt"
)
func main() {
err := errors.New("错误信息...")
fmt.Println(err)
num, err2 := Calculation(0)
fmt.Println(num, err2)
}
//通过内置errors包创建错误对象来返回
func Calculation(divisor int) (int, error) {
if divisor == 0 {
return 0, errors.New("错误:除数不能为零.")
}
return 100 / divisor, nil
}</code></pre>