空接口
空接口中没有任何方法。任意类型都可以实现该接口。空接口这样定义:interface{},也就是包含0个方法(method)的interface。空接口可表示任意数据类型,类似于Java中的object。
空接口常用于以下情形。
- println的参数就是空接口。
- 定义一个map:key是string,value是任意数据类型。
- 定义一个切片,其中存储任意类型的数据。
使用方法:
package main
import "fmt"
type A interface {
}
type Man struct {
name string
age int
}
type Woman struct {
name string
age int
}
func main() {
var a1 A = Man{"Li", 22}
var a2 A = Woman{"Lily", 19}
var a3 A = "This is string"
var a4 A = 1008
printVar(a1)
printVar(a2)
printVar(a3)
printVar(a4)
}
func printVar(a A) {
fmt.Printf("%T, %v, %p \n", a, a, &a)
}
// 输出内容:
// main.Man, {Li 22}, 0xc0001021e0
// main.Woman, {Lily 19}, 0xc0001021f0
// string, This is string, 0xc000102200
// int, 1008, 0xc000102210
变量 a1、a2、a3、a4 都是不同的数据类型的变量,但是它们都实现了空接口,所以都可以存放在空接口中使用。
2. 类型断言
接口对象断言方式一:
instance, ok := 接口对象.(类型)
如果该接口对象是对应的实际类型,那么instance就是转型之后的对象,ok的值为true,配合if … else if…语句使用。
接口对象断言方式二:
接口对象.(类型)
此方式配合 switch…case 语句使用。
接下来通过一个案例实现接口对象断言,具体示例如下:
package main
import (
"fmt"
"math"
)
// 1. 定义接口
type Shape interface {
perimeter() float64
area() float64
}
// 2. 矩形
type Rectangle struct {
a, b float64
}
// 3. 三角形
type Triangle struct {
a, b, c float64
}
// 4. 圆形
type Circle struct {
radius float64
}
// 定义接口实现的方法
func (r Rectangle) perimeter() float64 {
return (r.a + r.b) * 2
}
func (r Rectangle) area() float64 {
return r.a * r.b
}
func (r Triangle) perimeter() float64 {
return r.a + r.b + r.c
}
func (r Triangle) area() float64 {
p := r.perimeter() / 2
return math.Sqrt(p * (p - r.a) * (p - r.b) * (p - r.c))
}
func (r Circle) perimeter() float64 {
return 2 * math.Pi * r.radius
}
func (r Circle) area() float64 {
return math.Pow(r.radius, 2) * math.Pi
}
// 接口对象断言1
func getType(s Shape) {
if instance, ok := s.(Rectangle); ok {
fmt.Printf("是矩形:长:%.2f, 宽:%.2f \n", instance.a, instance.b)
} else if instance, ok := s.(Triangle); ok {
fmt.Printf("是三角形:分别是:%.2f、%.2f、%.2f \n", instance.a, instance.b, instance.c)
} else if instance, ok := s.(Circle); ok {
fmt.Printf("是圆形:半径:%.2f \n", instance.radius)
}
}
// 方式二:使用 switch 语句
func getType2(s Shape) {
switch instance := s.(type) {
case Rectangle:
fmt.Printf("是矩形:长:%.2f, 宽:%.2f \n", instance.a, instance.b)
case Triangle:
fmt.Printf("是三角形:分别是:%.2f、%.2f、%.2f \n", instance.a, instance.b, instance.c)
case Circle:
fmt.Printf("是圆形:半径:%.2f \n", instance.radius)
}
}
func getResult(s Shape) {
getType2(s)
fmt.Printf("周长:%.2f 面积:%。2f \n", s.perimeter(), s.area())
}
func main() {
var s Shape
s = Rectangle{3, 4}
getResult(s)
printVar(s)
s = Triangle{3, 4, 5}
getResult(s)
printVar(s)
s = Circle{2}
getResult(s)
printVar(s)
tt := Triangle{3, 4, 5}
fmt.Println(tt)
}
func (t Triangle) String() string { // 实现系统接口,更改部分打印结果
return fmt.Sprintf("Triangle 对象,属性分别是:%.2f, %.2f, %2f \n", t.a, t.b, t.c)
}
func printVar(s Shape) {
fmt.Printf("%T, %v, %p \n", s, s, &s)
fmt.Printf("-----------------------------\n")
}
// 是矩形:长:3.00, 宽:4.00
// 周长:14.00 面积:%!。(float64=12)2f
// main.Rectangle, {3 4}, 0xc000010200
// -----------------------------
// 是三角形:分别是:3.00、4.00、5.00
// 周长:12.00 面积:%!。(float64=6)2f
// main.Triangle, Triangle 对象,属性分别是:3.00, 4.00, 5.000000
// , 0xc000010210
// -----------------------------
// 是圆形:半径:2.00
// 周长:12.57 面积:%!。(float64=12.566370614359172)2f
// main.Circle, {2}, 0xc000010220
// -----------------------------
// Triangle 对象,属性分别是:3.00, 4.00, 5.000000