zoukankan      html  css  js  c++  java
  • 【原创】go语言学习(十六)接口

    目录

    • 接口介绍与定义
    • 空接口和类型断言
    • 指针接收和值接收区别
    • 接口嵌套

    接口介绍与定义

    1、 接口定义了一个对象的行为规范

    A. 只定义规范,不实现
    B. 具体的对象需要实现规范的细节

    2、Go中接口定义

    A. type 接口名字 interface
    B. 接口里面是一组方法签名的集合

    type Animal interface {
        Talk()
        Eat() int
        Run()
    }
    

      

    3、Go中接口的实现

    A. 一个对象只要包含接口中的方法,那么就实现了这个接口
    B. 接口类型的变量可以保存具体类型的实例

    type Animal interface {
        Talk()
        Eat() int
        Run()
    }
    

      

    4、接口实例

    A. 一个公司需要计算所有职员的薪水
    B. 每个职员的薪水计算方式不同

    package main
    
    import (
    	"fmt"
    )
    
    type Employer interface {
    	CalcSalary() float32
    }
    
    type Programer struct {
    	name  string
    	base  float32
    	extra float32
    }
    
    func NewProgramer(name string, base float32, extra float32) Programer {
    	return Programer{
    		name:  name,
    		base:  base,
    		extra: extra,
    	}
    }
    
    func (p Programer) CalcSalary() float32 {
    	return p.base
    }
    
    type Sale struct {
    	name  string
    	base  float32
    	extra float32
    }
    
    func NewSale(name string, base, extra float32) Sale {
    	return Sale{
    		name:  name,
    		base:  base,
    		extra: extra,
    	}
    }
    
    func (p Sale) CalcSalary() float32 {
    	return p.base + p.extra*p.base*0.5
    }
    
    func calcALL(e []Employer) float32 {
    	var cost float32
    	for _, v := range e {
    		cost = cost + v.CalcSalary()
    	}
    
    	return cost
    }
    
    func main() {
    	p1 := NewProgramer("搬砖1", 1500.0, 0)
    	p2 := NewProgramer("搬砖2", 1500.0, 0)
    	p3 := NewProgramer("搬砖3", 1500.0, 0)
    
    	s1 := NewSale("销售1", 800.0, 2.5)
    	s2 := NewSale("销售2", 800.0, 2.5)
    	s3 := NewSale("销售3", 800.0, 2.5)
    
    	var employList []Employer
    	employList = append(employList, p1)
    	employList = append(employList, p2)
    	employList = append(employList, p3)
    
    	employList = append(employList, s1)
    	employList = append(employList, s2)
    	employList = append(employList, s3)
    
    	cost := calcALL(employList)
    	fmt.Printf("这个月的人力成本:%f
    ", cost)
    
    }
    

      

    5、接口类型变量

    A. var a Animal
    B. 那么a能够存储所有实现Animal接口的对象实例

    package main
    
    import "fmt"
    
    type Animal interface {
    	Talk()
    	Eat()
    	Name() string
    }
    
    type Dog struct {
    }
    
    func (d Dog) Talk() {
    	fmt.Println("汪汪汪")
    }
    
    func (d Dog) Eat() {
    	fmt.Println("我在吃骨头")
    }
    
    func (d Dog) Name() string {
    	fmt.Println("我的名字叫旺财")
    	return "旺财"
    }
    
    type Pig struct {
    }
    
    func (d Pig) Talk() {
    	fmt.Println("坑坑坑")
    }
    
    func (d Pig) Eat() {
    	fmt.Println("我在吃草")
    }
    
    func (d Pig) Name() string {
    	fmt.Println("我的名字叫八戒")
    	return "八戒"
    }
    
    func testInterface1() {
    	var d Dog
    	var a Animal
    	a = d
    
    	a.Eat()
    	a.Talk()
    	a.Name()
    
    	var pig Pig
    	a = pig
    	a.Eat()
    	a.Talk()
    	a.Name()
    }
    
    func just(a Animal) {
    	// d, ok := a.(Dog)
    	// p, ok := a.(Pig)
    	switch v := a.(type) {
    	case Dog:
    		fmt.Printf("v is dog, %v
    ", v)
    	case Pig:
    		fmt.Printf("v is dog, %v
    ", v)
    	default:
    		fmt.Printf("not support")
    	}
    }
    
    func testInterface2() {
    	var d Dog
    	just(d)
    }
    
    func main() {
    	//testInterface1()
    	testInterface2()
    }
    

      

    空接口和类型断言

    1、空接口

    A. 空接口没有定义任何方法
    B. 所以任何类型都实现了空接口

    interface {
    }
    

      

    package main
    
    import "fmt"
    
    func describe(a interface{}) {
    	fmt.Printf("%T %v
    ", a, a)
    }
    
    func testInterface() {
    	var a interface{}
    	var b int = 100
    	a = b
    
    	fmt.Printf("%T %v
    ", a, a)
    
    	var c string = "hello"
    	a = c
    	fmt.Printf("%T %v
    ", a, a)
    
    	var d map[string]int = make(map[string]int, 100)
    	d["abc"] = 1000
    	d["eke"] = 30
    
    	a = d
    	fmt.Printf("%T %v
    ", a, a)
    }
    
    type Student struct {
    	Name string
    	Sex  int
    }
    
    func main() {
    
    	a := 65
    	describe(a)
    
    	str := "hello"
    	describe(str)
    
    	var stu Student = Student{
    		Name: "user01",
    		Sex:  1,
    	}
    
    	describe(stu)
    }
    

      

    2、类型断言

    A. 如何获取接口类型里面存储的具体的值呢?

    B.类型断言的坑

    C.如何解决,引入 ok判断机制! v, ok := i.(T)

    D.type switch。

    E.type switch另外一种写法,解决转两次的问题

    package main
    
    import "fmt"
    
    // 类型断言
    func test(a interface{}) {
    	s, ok := a.(int)
    	if ok {
    		fmt.Println(s)
    		return
    	}
    	str, ok := a.(string)
    	if ok {
    		fmt.Println(str)
    		return
    	}
    
    	f, ok := a.(float32)
    	if ok {
    		fmt.Println(f)
    		return
    	}
    
    	fmt.Println("can not define the type of a")
    
    }
    
    func testInterface1() {
    	var a int = 100
    	test(a)
    
    	var b string = "hello"
    	test(b)
    }
    
    // case优雅实现(二次转换)
    func testSwitch(a interface{}) {
    	switch a.(type) {
    	case string:
    		fmt.Printf("a is string, value: %v", a.(string))
    	case int:
    		fmt.Printf("a is int, value: %v", a.(int))
    	case int32:
    		fmt.Printf("a is not, value: %v", a.(int32))
    	default:
    		fmt.Println("no support type")
    	}
    }
    
    func testInterface2() {
    	var a int = 100
    	testSwitch(a)
    
    	var b string = "hellow"
    	testSwitch(b)
    }
    
    // case优雅实现(一次转换)
    func testSwitch2(a interface{}) {
    	switch v := a.(type) {
    	case string:
    		fmt.Printf("a is string, value: %v", v)
    	case int:
    		fmt.Printf("a is int, value: %v", v)
    	case int32:
    		fmt.Printf("a is not, value: %v", v)
    	default:
    		fmt.Println("no support type")
    	}
    }
    
    func testInterface3() {
    	var a int = 100
    	testSwitch2(a)
    
    	var b string = "hellow"
    	testSwitch2(b)
    }
    
    func main() {
    	testInterface1()
    	testInterface2()
    	testInterface3()
    }
    

      

    指针接收和值接收区别

    1、指针接收

    package main
    
    import "fmt"
    
    type Animal interface {
    	Talk()
    	Eat()
    	Name() string
    }
    
    type Dog struct {
    }
    
    func (d *Dog) Talk() {
    	fmt.Println("汪汪汪")
    }
    
    func (d *Dog) Eat() {
    	fmt.Println("我在吃骨头")
    }
    
    func (d *Dog) Name() string {
    	fmt.Println("我的名字叫旺财")
    }
    
    func main() {
    	var a Animal
    	// 值
    	// a存的是一个值类型的Dog,那么调用a.Eat(). &Dog ->Eat()
    	// 如果一个变量存储在接口类型的变量中之后,那么不能获取这个变量的地址
    	//var d Dog
    	//a = d
    	//a.Eat()
    	//
    	//fmt.Printf("%T %v
    ", a, a)
    
    	// 指针
    	var d1 *Dog = &Dog{}
    	a = d1
    	// *(&Dog).Eat()
    	a.Eat()
    	fmt.Printf("*Dog %T %v
    ", d1, d1)
    }
    

      

    接口嵌套

    1、 实现多接口,同一个类型可以实现多个接口

    2、 接口嵌套,和结构体嵌套类似

    package main
    
    import "fmt"
    
    type Animal interface {
    	Talk()
    	Eat()
    	Name() string
    }
    
    type PuruDongwu interface {
    	TaiSheng()
    }
    
    type Dog struct {
    }
    
    func (d Dog) Talk() {
    	fmt.Println("汪汪汪")
    }
    
    func (d Dog) Eat() {
    	fmt.Println("我在吃骨头")
    }
    
    func (d Dog) Name() string {
    	fmt.Println("我的名字叫旺财")
    	return "旺财"
    }
    
    func (d Dog) TaiSheng() {
    	fmt.Println("狗是胎生的")
    }
    
    func main() {
    	var d Dog
    	var a Animal
    
    	fmt.Printf("%v %T %p", a, a, a)
    
    	if a == nil {
    		fmt.Println("a is nil")
    	}
    
    	a = d
    	a.Eat()
    
    	var b PuruDongwu
    	b = d
    	b.TaiSheng()
    }
    

      

  • 相关阅读:
    阿里terway源码分析
    golang timeoutHandler解析及kubernetes中的变种
    第四章 控制和循环
    关于 自媒体的声明
    java用正则表达式获取url的域名
    javaweb三大核心基础技术
    NumPy之计算两个矩阵的成对平方欧氏距离
    C/C++之计算两个整型的平均值
    C/C++代码优化之整型除以2的指数并四舍五入
    SSE系列内置函数中的shuffle函数
  • 原文地址:https://www.cnblogs.com/wangshuyang/p/11815147.html
Copyright © 2011-2022 走看看