接口
关键字interface{}
空接口
可以将所有的类型变量赋值给空接口,空接口可以进行类型断言,再转换为具体的类型变量
定义空接口的格式:
var 变量名 interface{}
例子:空接口赋值与类型推断
package main
import (
"fmt"
)
func main() {
// 定义并赋值一个变量v1
var v1 int = 54
// 将变量赋值给一个空接口i1
var i1 interface{} = v1
// 定义一个变量v2
var v2 int
// 对空接口i1进行类型推断,推断成功的话会把值赋给变量v2
v2, _ = i1.(int)
fmt.Println(v2)
}
以上代码的运行结果:
54
类型接口
接口可用于定义一套标准的可操作行为规范,其中包含了各种方法的定义规范。与其他语言不同,golang的接口是一种非侵入式的接口,在类型定义的过程中中不需要知道接口的存在,只会在接口赋值时去判断类型与接口是否匹配。通过这种非侵入式的接口可以更进一步地对代码进行解耦。
定义接口的格式:
type 类型名称 interface {
方法名(传入参数)返回参数
...
}
例子:接口调用
package main
import (
"fmt"
)
// 定义一个Runner接口,其中包含Run()方法
type Runner interface {
Run()
}
// 定义一个Swimmer接口,其中包含Swim()方法
type Swimmer interface {
Swim()
}
// 定义一个Cat类型
type Cat struct{}
// Cat类型实现了Run方法,说明猫是Runner
func (c Cat) Run() {
fmt.Println("cat can run.")
}
// 定义一个Dog类型
type Dog struct{}
// Dog类型实现了Run方法,说明狗是Runner
func (d Dog) Run() {
fmt.Println("dog can run.")
}
// Dog类型实现了Swim方法,说明狗是Swimmer
func (d Dog) Swim() {
fmt.Println("dog can swim.")
}
func main() {
// 定义一个Runner接口变量runner,默认值nil
var runner Runner
// 定义一个Swimmer接口变量swimmer,默认值nil
var swimmer Swimmer
// 实例化一个Cat类型变量cat
var cat Cat
// 实例化一个Dog类型变量dog
var dog Dog
// 将cat赋值给接口runner
runner = cat
// 通过runner执行cat的Run()方法
runner.Run()
// 将dog赋值给接口runner
runner = dog
// 通过runner执行dog的Run()方法
runner.Run()
// 将dog赋值给接口swimmer
swimmer = dog
// 通过swimmer执行dog的Swim()方法
swimmer.Swim()
}
以上代码的执行结果:
cat can run.
dog can run.
dog can swim.
可以这么理解,接口只关心类型能否去执行某个方法,而不会去关心类型中有什么值
类型推断
将接口类型变量转换成其它类型需要使用类型推断,有三种书写方式:
方式一
{{ 推断后的变量 }} := {{ 接口变量 }}.({{ 推断类型 }})
方式二
{{ 推断后的变量 }}, {{ 是否推断成功 }} := {{ 接口变量 }}.({{ 推断类型 }})
方式三
switch {{ 推断后的变量 }}:={{ 接口变量 }}.(type){
case {{ 推断类型1 }}:
...
case {{ 推断类型2 }}:
...
default:
...
}
对于参数类型不确定的情况,推荐使用方式三
例子:通过类型推断对接口变量进行格式转换
package main
import "fmt"
func main() {
var i interface{}
// 类型推断方式一
i = 666
var v1 int
v1 = i.(int)
fmt.Printf("int:%d\n", v1)
// 类型推断方式二
i = "hello"
var v2 string
v2, ok := i.(string)
if !ok{
panic("not a string type")
}
fmt.Printf("string:%s\n", v2)
// 类型推断方式三
i = 3.1415926
var v3 float64
switch v:=i.(type){
case float64:
v3 = v
default:
panic("not type of float64")
}
fmt.Printf("float:%f\n", v3)
}
最后更新于