教程集 www.jiaochengji.com
教程集 >  Golang编程  >  golang教程  >  正文 【Golang】go语言面向接口

【Golang】go语言面向接口

发布时间:2022-01-24   编辑:jiaochengji.com
教程集为您提供【Golang】go语言面向接口等资源,欢迎您收藏本站,我们将为您提供最新的【Golang】go语言面向接口资源

Go语言的接口是一种抽象数据类型,是一系列接口的集合,接口把所有的具有共性的方法定义在一起,任何其它类型只要实现了接口定义的方法就是实现了接口。接口是duck-type编程的一种体现,不关心属性(数据),只关心行为(方法)。

<pre class="has"><code class="language-Go">type 接口类型名 interface{ 方法名1(参数列表)(返回值) 方法名2(参数列表)(返回值) ... } type Fruit interface{ Color(color string) Num(n int) }</code></pre>

在 go 中实现接口很简单,不需要显式的声明实现了某个接口,想要实现某个接口,只需要实现接口中的所有方法即可。

<pre class="has"><code class="language-Go">type Fruit interface { Color() (color string) Num() (n int) } type Apple struct { Col string N int } func (apple Apple) Color() (color string) { fmt.Println(apple.Col) return apple.Col } func (apple Apple) Num() (n int) { fmt.Println(apple.N) return apple.N } type Orange struct { Col string N int } func (orange Orange) Color() (color string) { fmt.Println(orange.Col) return orange.Col } func (orange Orange) Num() (n int) { fmt.Println(orange.N) return orange.N }</code></pre>

上面定义了两个结构体类型和一个接口,下面我们通过程序把实现的类型和接口联系起来
可以将一个实现接口的对象实例赋值给接口,也可以将另外一个接口赋值给接口。
将一个类对象实例赋值给一个接口前,要保证类实现了接口的所有方法。

<pre class="has"><code class="language-Go">package main import "fmt" type Fruit interface { Color() (color string) Num() (n int) } type Apple struct { Col string N int } func (apple Apple) Color() (color string) { fmt.Println(apple.Col) return apple.Col } func (apple Apple) Num() (n int) { fmt.Println(apple.N) return apple.N } type Orange struct { Col string N int } func (orange Orange) Color() (color string) { fmt.Println(orange.Col) return orange.Col } func (orange Orange) Num() (n int) { fmt.Println(orange.N) return orange.N } func main() { apple := Apple{"red", 10} orange := Orange{"yellow", 5} var fruit Fruit fruit = apple fruit.Color() fruit.Num() fruit = orange orange.Color() orange.Num() }</code></pre>

程序运行之后结果如下:

接口变量存储了两部分信息,一个是分配给接口变量的具体值(接口实现者的值),一个是值的类型的描述器(接口实现者的类型),形式是(value, concrete type),而不是(value, interface type)。
实现接口的具体方法时,如果以指针作为接收者,接口的具体实现类型只能以指针方式使用,值接收者既可以按指针方式使用也可以按值方式使用。

<pre class="has"><code class="language-Go">package main import "fmt" type Retriever interface { Get(url string) string } type MockRetriever struct { Contents string } // 值接收者 func (r MockRetriever) Get(url string) string { return r.Contents } type RealRetriever struct { Contents string } // 指针接收者 func (r *RealRetriever) Get(url string) string { return r.Contents } func main() { var retriever Retriever retriever = MockRetriever{"This is fake Retreiver"} fmt.Printf("%T %v\n", retriever, retriever) retriever = &MockRetriever{"This is fake Retreiver"} fmt.Printf("%T %v\n", retriever, retriever) retriever = &RealRetriever{"This is real Retriever"} //retriever = RealRetriever{"This is real Retriever"} //error fmt.Printf("%T %v\n", retriever, retriever) }</code></pre>

空接口类型interface{}一个方法签名也不包含,所以所有的数据类型都实现了空接口。
空接口类型可以用于存储任意数据类型的实例。
如果一个函数的参数是空接口类型interface{},表明可以使用任何类型的数据。如果一个函数返回一个空接口类型,表明函数可以返回任何类型的数据。
interface{}可用于向函数传递任意类型的变量,但对于函数内部,该变量仍然为interface{}类型(空接口类型),而不是传入的实参类型。
利用接口类型作为参数可以达到抽象数据类型的目的。

interface{}可用于向函数传递任意类型的变量,但对于函数内部,该变量仍然为interface{}类型(空接口类型),而不是传入的实参类型。
类型断言是一个使用在接口值上的操作
有时候,我们可能需要知道某个接口类型的实际类型,比如某个方法需要接收多种类型的数据并需做分别处理时,我们可以把形参设为空接口类型以接收任意类型的值,但是我们怎么反向知道里面实际保存了的是哪个类型的对象呢? 

接口类型向普通类型的转换称为类型断言(运行期确定)。

value,ok := x.(T)
x表示一个接口类型,T表示一个类型,也可以是接口类型。
该断言表达式会返回x的值和一个布尔值 可根据该布尔值判断x是否为T类型。

<pre class="has"><code class="language-Go">package main import "fmt" type Person struct { Name string Age int } type IntSlice []int func Print1(obj interface{}) { //普通类型 value, ok := obj.(int) if ok { fmt.Println("int") fmt.Println(value) } else { fmt.Println("type error") } } func Print2(obj interface{}) { //结构体类型 value, ok := obj.(Person) if ok { fmt.Println("Person") fmt.Println(value.Name, value.Age) } else { fmt.Println("type error") } } func Print3(obj interface{}) { //切片类型 value, ok := obj.(IntSlice) if ok { fmt.Println("Slice") fmt.Println(value) } else { fmt.Println("type error") } } func main() { var value int = 20 Print1(value) person := Person{"jack", 25} Print2(person) slice := IntSlice{1, 2, 3, 4, 5} Print3(slice) }</code></pre>

程序运行结果:

断言失败在编译阶段不会报错,因此,如果不对断言结果进行判断将可能会断言失败导致运行错误。
不同类型变量的运算必须进行显式的类型转换,否者结果可能会溢出,导致出错。
类型断言也可以配合switch语句进行判断。

<pre class="has"><code>var t interface{} t = functionOfSomeType() switch t := t.(type) { default: fmt.Printf("unexpected type %T", t) // %T prints whatever type t has case bool: fmt.Printf("boolean %t\n", t) // t has type bool case int: fmt.Printf("integer %d\n", t) // t has type int case *bool: fmt.Printf("pointer to boolean %t\n", *t) // t has type *bool case *int: fmt.Printf("pointer to integer %d\n", *t) // t has type *int }</code></pre>

 

到此这篇关于“【Golang】go语言面向接口”的文章就介绍到这了,更多文章或继续浏览下面的相关文章,希望大家以后多多支持JQ教程网!

您可能感兴趣的文章:
Golang 基础教程
GO语言使用之面向对象编程(1)——Golang语言面向对象编程说明
想系统学习GO语言(Golang
关于Golang的介绍
Go核心编程-面向对象 [OOP]
关于golang面向接口
Go语言面向接口之接口的组合
[golang] 为什么接口变量的值不是nil?
Go语言接口interface
go 获取函数地址_Go语言基础--接口浅析

[关闭]
~ ~