接口
1:认识接口
在 Golang 中,接口(Interface)是一种类型,它是由一组方法组成的集合。一个类型只要实现了接口中的所有方法,就可以被视为该接口类型的实例。一个类型可以同时实现多个接口,从而具备多个不同的行为。
接口的定义格式为:
type 接口名 interface { 方法名1(参数列表1) 返回值列表1 方法名2(参数列表2) 返回值列表2 // ... }
其中,接口名首字母通常是大写的,以表示公开的接口类型。每个方法定义了接口的一部分功能,它们由函数签名组成,包括方法名、输入参数和返回值。实现接口的类型必须提供方法的完整实现。
例如,下面是一个简单的接口定义:
type Animal interface { Speak() string }
这个接口规定了一个
Speak()
方法,返回字符串。实现这个接口的类型必须提供一个Speak()
方法,它返回一个字符串类型的值。
我自己的代码示例
package retrieve2
import (
"io/ioutil"
"net/http"
)
type Retriever struct {
}
func (Retriever) Get(url string) string {
resp, err := http.Get(url)
if err != nil {
panic(err)
}
defer resp.Body.Close()
bytes, _ := ioutil.ReadAll(resp.Body)
return string(bytes)
}
package main
import (
"fmt"
retrieve2 "golang/Inter/retrieve2"
)
func getRrtiver() retriver {
return retrieve2.Retriever{}
}
type retriver interface {
Get(string) string
}
func main() {
var r retriver = getRrtiver()
fmt.Println(r.Get("https://www.imooc.com"))
}
2:接口的定义
1:
package main
import (
"fmt"
"go1.19/retriever/mooc"
)
func download(r Retriever) string {
return r.Get("htts://www.imooc.com")
}
type Retriever interface {
Get(string) string
}
func main() {
var r Retriever
r = mooc.Retriever{"this is a imooc com "}
fmt.Println(download(r))
}
2:
package real
import (
"net/http"
"net/http/httputil"
"time"
)
type Retriever struct {
UseAgent string
Timeout time.Duration
}
func (r Retriever) Get(url string) string {
resp, err := http.Get(url)
if err != nil {
panic(err)
}
result, err := httputil.DumpResponse(resp, true)
resp.Body.Close()
if err != nil {
panic(err)
}
return string(result)
}
3:接口值的类型
3/1:接口类型判断
在Go语言中,类型断言是一种将接口类型转换为其他类型的方法。它可以用于检查接口类型是否实现了某个特定的接口,或者将接口类型转换为具体的类型。
Go语言中的类型断言有两种形式:类型断言表达式和类型断言语句。
类型断言表达式的语法如下:
value, ok := interfaceVar.(Type)
其中,interfaceVar
是一个接口类型的变量,Type
是一个具体的类型。如果interfaceVar
实现了Type
接口,那么value
将会是interfaceVar
转换为Type
类型后的值,ok
将会是true
。如果interfaceVar
没有实现Type
接口,那么value
将会是Type
类型的零值,ok
将会是false
。
下面是一个示例:
var i interface{} = "hello"
s, ok := i.(string)
if ok {
fmt.Println(s)
}
在这个示例中,我们将一个字符串类型的值赋给了一个接口类型的变量i
。然后,我们使用类型断言表达式将i
转换为字符串类型,并将结果赋给s
。由于i
实现了string
类型的接口,所以ok
的值为true
,我们可以打印出s
的值。
类型断言语句的语法如下:
value := interfaceVar.(Type)
其中,interfaceVar
是一个接口类型的变量,Type
是一个具体的类型。如果interfaceVar
实现了Type
接口,那么value
将会是interfaceVar
转换为Type
类型后的值。如果interfaceVar
没有实现Type
接口,那么程序将会抛出一个运行时错误。
下面是一个示例:
var i interface{} = "hello"
s := i.(string)
fmt.Println(s)
在这个示例中,我们将一个字符串类型的值赋给了一个接口类型的变量i
。然后,我们使用类型断言语句将i
转换为字符串类型,并将结果赋给s
。由于i
实现了string
类型的接口,所以我们可以打印出s
的值。
需要注意的是,类型断言只能用于接口类型的变量。如果您尝试将一个非接口类型的变量转换为其他类型,那么程序将会抛出一个编译时错误。
package main
import (
"fmt"
"go1.19/retriever/mooc"
real2 "go1.19/retriever/real2"
"time"
)
func download(r Retriever) string {
return r.Get("htts://www.imooc.com")
}
func inspect(r Retriever) {
fmt.Printf("%T , %v", r, r)
switch v := r.(type) {
case mooc.Retriever:
fmt.Println("contents", v.Contents)
case *real2.Retriever:
fmt.Println(v.UseAgent)
}
}
type Retriever interface {
Get(string) string
}
func main() {
var r Retriever
//这个地方也可以是一个指针
r = &mooc.Retriever{"this is a imooc com "}
inspect(r)
fmt.Println(download(r))
r = &real2.Retriever{
UseAgent: "jon",
Timeout: time.Second,
}
inspect(r)
// type assetion
if moocRetriever, ok := r.(mooc.Retriever); ok {
fmt.Println(moocRetriever)
} else {
fmt.Println("not a mook retriever")
}
}
3/2:空接口
在Go语言中,interface{}
类型是一种特殊的类型,它可以表示任何类型的值。这使得interface{}
类型非常灵活,可以用于编写通用的代码,但也使得它有些抽象和难以理解。
下面是一个示例,演示如何使用interface{}
类型:
package main
import "fmt"
func main() {
var i interface{}
i = 42
fmt.Printf("%T %v\n", i, i)
i = "hello"
fmt.Printf("%T %v\n", i, i)
i = []int{1, 2, 3}
fmt.Printf("%T %v\n", i, i)
}
在这个示例中,我们首先定义了一个interface{}
类型的变量i
。然后,我们将不同类型的值分别赋给i
,包括整数、字符串和整数切片。最后,我们使用fmt.Printf
函数打印出i
的类型和值。
需要注意的是,当我们将一个值赋给interface{}
类型的变量时,Go语言会将该值的类型信息保存在变量中。当我们从interface{}
类型的变量中获取值时,我们需要使用类型断言来将其转换为具体的类型。例如,如果我们想将i
转换为整数切片类型,可以使用以下代码:
s := i.([]int)
fmt.Printf("%T %v\n", s, s)
在这个示例中,我们使用类型断言将i
转换为整数切片类型,并将结果赋给s
。然后,我们使用fmt.Printf
函数打印出s
的类型和值。
需要注意的是,如果我们使用类型断言将interface{}
类型的变量转换为错误的类型,或者该变量不包含任何值,程序将会抛出一个运行时错误。因此,在使用类型断言时,我们需要确保变量中包含了正确的类型信息。