Go- 接口 -1
发布于: 3 小时前
Go 学习笔记,学习内容《Go入门指南》
主要介绍以下内容:
接口类型的定义
接口赋值
接口数组
接口嵌套
接口变量类型-var.(T)
接口变量类型-type-switch
如何获得各种变量的类型
代码示例可以直接运行
package main
import (
"fmt"
"reflect"
)
func printDivider(str ...string) {
fmt.Println()
fmt.Println("-----------------------------------------------")
if len(str) > 0 {
fmt.Println(str)
}
}
type Shaper interface { // 接口名称使用er结尾
Area() float32
}
type Square struct {
side float32
}
func (sq *Square) Area() float32 { // 实现接口的方法
return sq.side * sq.side
}
type Circular struct {
redius float32
}
func (cir *Circular) Area() float32 {
return 3.14 * cir.redius * cir.redius
}
func (cir *Circular) Perimeter() float32 {
return 2 * 3.14 * cir.redius
}
type Color interface {
Rgb() string
}
type Object interface {
Color
Shaper
}
type Paper struct {
redius float32
color string
}
func (p *Paper) Area() float32 {
return 3.14 * p.redius * p.redius
}
func (p *Paper) Rgb() string {
return p.color + "." + p.color + "." + p.color
}
func main() {
/*
接口类型的定义
接口定义一组方法接口,仅声明方法,不实现方法。通常定义0-3个方法
接口中不能包含变量
接口名字通常使用(e)r结尾,如Reader、Writer、Logger等
一个类型可以实现多个接口
*/
printDivider("接口类型的定义")
sq1 := new(Square)
sq1.side = 2
var areaIntf Shaper
areaIntf = sq1 // sq1必须是一个指针,不能是一个实例
fmt.Println(areaIntf.Area()) // 输出:4
/*
接口赋值
必须实现接口的方法才可以对接口类型进行赋值
*/
printDivider("接口赋值")
rd1 := new(Circular)
rd1.redius = 1.2
//若接口体Circular没有实现 Shaper 接口的 Area方法
//areaIntf = rd1 // 编译错误:cannot use rd1 (type *Circular) as type Shaper in assignment: *Circular does not implement Shaper (missing Area method)
// 结构体Circular除了Area方法,也可以实现其他方法
areaIntf = rd1
fmt.Println(areaIntf.Area())
//fmt.Println(areaIntf.Perimeter()) 编译错误:areaIntf.Perimeter undefined (type Shaper has no field or method Perimeter)
/*
接口数组
*/
printDivider("接口数组")
sq2 := &Square{5}
rd2 := &Circular{2}
shapes := []Shaper{sq2, rd2}
for n, _ := range shapes {
fmt.Println("Sharper details: ", shapes[n])
fmt.Println("Sharper Area: ", shapes[n].Area())
}
/*
输出:
Sharper details: &{5}
Sharper Area: 25
Sharper details: &{2}
Sharper Area: 12.56
*/
/*
接口嵌套
*/
printDivider("接口嵌套")
p1 := &Paper{3, "255"}
//var obj1 Object
obj1 := p1
fmt.Println(obj1.Area()) // 输出:28.26
fmt.Println(obj1.Rgb()) // 输出:255.255.255
/*
接口变量类型-var.(T)
*/
printDivider("接口变量类型-var.(T)")
if t, ok := shapes[0].(*Square); ok {
fmt.Printf("The TYpe of shapes[0] is : %T\n", t) // 输出:The TYpe of shapes[0] is : *main.Square
}
if t, ok := shapes[1].(*Circular); ok {
fmt.Printf("The Type of shapes[1] is : %T\n", t) // 输出:The Type of shapes[1] is : *main.Circular
}
/*
接口变量类型-type-switch
*/
printDivider("接口变量类型-type-switch")
switch t := areaIntf.(type) {
case *Square:
fmt.Printf("Type Square %T with value %v\n", t, t) // 输出:Type Circular *main.Circular with value &{1.2}
case *Circular:
fmt.Printf("Type Circular %T with value %v\n", t, t)
default:
fmt.Printf("I don not know who you are.")
}
/*
如何获得各种变量的类型
*/
printDivider("如何获得各种变量的类型")
classifier(1, 2)
classifier("a", 100)
/* var.(Type)只能用于简单数据类型,不能用于array, slice, map */
//var x1 [5]string
//fmt.Println(x1.(Type)) // 编译错误:invalid type assertion: x1.(Type) (non-interface type [5]string on left)
x2 := []int{1, 2, 3}
fmt.Printf("Type: %T\n", x2) // 输出:Type: []int
t := reflect.TypeOf(x2).String() // 可以使用reflect.TypeOf判断array, slice, map的类型
if t == "[]int" {
fmt.Println("TypeOf: []int") // 输出: TypeOf: []int
}
x3 := x2[:2]
fmt.Printf("Type: %T\n", x3) // 输出:Type: []int
t = reflect.TypeOf(x3).String() // 可以使用reflect.TypeOf判断array, slice, map的类型
if t == "[]int" {
fmt.Println("TypeOf: []int") // 输出: TypeOf: []int
}
x4 := map[string]string{"a": "1", "b": "2", "c": "3"}
fmt.Printf("Type: %T\n", x4) // 输出:Type: map[string]string
t = reflect.TypeOf(x4).String() // 可以使用reflect.TypeOf判断array, slice, map的类型
if t == "map[string]string" {
fmt.Println("TypeOf: map[string]string") // 输出:TypeOf: map[string]string
}
/*
测试值是否实现某个接口?
*/
}
/* 类型分类函数,可变参数,item是一个数组,数组里的元素可以是不同的类型*/
func classifier(items ...interface{}) {
for i, x := range items {
switch x.(type) {
case bool:
{
fmt.Printf("Param #%d is a bool\n", i)
}
case int, int64:
{
fmt.Printf("Param #%d is a int\n", i)
}
case float32, float64:
{
fmt.Printf("Param #%d is a float\n", i)
}
case string:
{
fmt.Printf("Param #%d is a string\n", i)
}
case nil:
{
fmt.Printf("Param #%d is a nil\n", i)
}
default:
{
fmt.Printf("Param #%d is x\n", i)
}
}
}
}
复制代码
划线
评论
复制
发布于: 3 小时前阅读数: 3
版权声明: 本文为 InfoQ 作者【HelloBug】的原创文章。
原文链接:【http://xie.infoq.cn/article/a95f0ccb2a58dd058fb3a9111】。
本文遵守【CC BY-NC-ND】协议,转载请保留原文出处及本版权声明。
HelloBug
关注
还未添加个人签名 2018.09.20 加入
还未添加个人简介
评论