> go语言接口(interface),类似其他语言的接口的作用,主要用于定义一组函数(方法)签名,不包括实现。
[TOC]
## 接口定义
> 语法
~~~
type 接口类型名 interface {
函数签名列表
}
~~~
> 例子
~~~
// 定义Book接口类型,里面包含一个Abs函数签名定义,不包括函数实现。
type Book interface {
Abs() float64
}
~~~
## 接口实现
> go语言实现接口,采用的是隐式实现方式,并不像java那样需要显示的implement接口,只需实现了接口中的方法,就认为实现了该接口
~~~
package main
import (
"fmt"
)
// 定义Book接口类型,里面包含一个Abs函数签名定义,不包括函数实现
type Book interface {
Abs() float64
}
// 定义一个MyFloat类型,它是float64的别名
type MyFloat float64
// 给MyFloat类型,定义一个Abs方法,计算绝对值
func (f MyFloat) Abs() float64 {
if f < 0 {
return float64(-f)
}
return float64(f)
}
// 定义ArtBook类型结构体
type ArtBook struct {
Price1, Price2 float64
}
// 为ArtBook类型定义Abs方法
func (book *ArtBook) Abs() float64 {
return book.Price1 + book.Price2
}
func main() {
// 定义Book接口变量
var book Book
// 定义MyFloat类型变量
f := MyFloat(-100.25)
// 因为MyFloat实现了,Book接口中定义的方法,所以可以赋值给接口类型变量
book = f
// 通过接口类型调用方法
fmt.Println(book.Abs())
// 定义ArtBook类型变量
v := ArtBook{Price1: 11, Price2: 20}
// 将ArtBook变量赋值给接口类型,这里之所以需要取地址符,因为*ArtBook类型实现了接口的Abs方法
book = &v
// 通过接口类型调用方法
fmt.Println(book.Abs())
}
~~~
> MyFloat和ArtBook并没有显式的说明实现Book接口,只要实现了Book接口的方法,就认为实现了该接口
## 接口变量默认值
> 没有初始化的接口变量,默认值是nil
~~~
var book Book
if book == nil {
fmt.Println("is nil")
}
fmt.Println(book)
~~~
## 空接口
> 包含0个方法的接口,就是空接口,如下
~~~
interface{}
~~~
### 空接口类型
> 空接口类型可以存储任意类型的数据,类似java的object类型
```
package main
import "fmt"
func main() {
// 定义空接口变量
var obj interface{}
// 赋值一个Int类型数据给空接口
obj = 42
fmt.Println(obj)
// 再赋值一个string类型数据给空接口
obj = "hello"
fmt.Println(obj)
}
```
### interface类型转换
> 转换语法:i 是interface{}类型变量,T是我们要转换的类型
```
t := obj.(要转换的类型)
```
> 例子
> 注意:interface{}类型转换,只能转换至真实的类型,通俗的讲就是,当初赋值给interface{}变量的是什么类型数据,就只能还原成什么类型数据
```
// 定义一个interface{}类型,并初始化为字符串
var obj interface{} = "hello"
// 转换成string类型
s := obj.(string)
```
### 判断Interface类型转换失败
> 语法:通过第二个返回值ok判断是否转换成功
```
value, ok := obj.(要转换的类型)
```
> 例子
```
var obj interface{} = "hello"
str, ok := obj.(string)
```
### interface类型判断
> 通过switch语句结合i.(type)语法,判断interface类型
```
package main
import "fmt"
func do(obj interface{}) {
// 通过switch判断i的类型
switch v := obj.(type) {
case int:
fmt.Println("是int类型,", v)
case string:
fmt.Println("是string类型,", v)
default:
fmt.Println("未知类型,", v)
}
}
func main() {
do(21)
do("hello")
do(true)
}
```
- 基础知识
- 开发环境
- 包名规则
- 包初始化 (init)
- 基础数据类型
- 基础类型转换
- 格式化输出
- go指针
- 流程控制语句
- 函数定义
- 匿名函数
- 数组和切片
- map集合
- 结构体
- Interface接口
- 日期处理
- 数学计算
- 正则表达式
- 协程 (并发处理)
- channel
- waitgroup
- mutex (锁机制)
- websocket
- protobuf
- Redis
- 错误处理
- 打包程序
- NSQ消息队列
- 单元测试
- beego
- 安装入门
- Gin
- 快速入门
- 路由与控制器
- 处理请求参数
- 表单验证
- 处理响应结果
- 渲染HTML模版
- 访问静态文件
- Gin中间件
- Cookie处理
- Session处理
- Gin上传文件
- swagger
- pprof性能测试
- GORM
- 入门教程
- 模型定义
- 数据库连接
- 插入数据
- 查询数据
- 更新数据
- 删除数据
- 事务处理
- 关联查询
- 属于 (BELONG TO)
- 一对一 (Has One)
- 一对多 (Has Many)
- 多对多 (Many to Many)
- 预加载 (Preloading)
- 错误处理
- 第三方常用插件
- viper 读取配置文件
- zap 高性能日志
- Nginx代理配置
- Goland 快捷键