1.定义 Interface是类型可以定义一组方法,但是这些不需要实现。并且interface不能包含任何变量。 比如:

type example interface{

        Method1(参数列表) 返回值列表
        Method2(参数列表) 返回值列表
        …
}

2.interface类型默认是一个指针

type example interface{

        Method1(参数列表) 返回值列表
        Method2(参数列表) 返回值列表
        …
}
var a example
a.Method1()

3.接口实现 a. Golang中的接口,不需要显示的实现。只要一个变量,含有接口类型中的所有方法,那么这个变量就实现这个接口。因此,golang中没有implement类似的关键字 b. 如果一个变量含有了多个interface类型的方法,那么这个变量就实现了多个接口。 c. 如果一个变量只含有了1个interface的方部分方法,那么这个变量没有实现这个接口。 4.多态 一种事物的多种形态,都可以按照统一的接口进行操作 5.接口嵌套 一个接口可以嵌套在另外的接口,如下所示:

 type ReadWrite interface {
               Read(b Buffer) bool
               Write(b Buffer) bool
} 
type Lock interface {
               Lock()
               Unlock() 
} 
type File interface {
               ReadWrite
               Lock 
               Close() 
} 
  1. 类型断言,由于接口是一般类型,不知道具体类型,如果要转成具体类型可以采用以下方法进行转换:
var t int
var x interface{}
x = t
y = x.(int)   //转成int

var t int
var x interface{}
x = t
y, ok = x.(int)   //转成int,带检查

7.练习,写一个函数判断传入参数的类型

 func classifier(items ...interface{}) {
          for i, x := range items { 
                  switch x.(type) {
                   case bool:       fmt.Printf(“param #%d is a bool\n”, i)
                   case float64:    fmt.Printf(“param #%d is a float64\n”, i)
                   case int, int64: fmt.Printf(“param #%d is an int\n”, i)
                   case nil: fmt.Printf(“param #%d is nil\n”, i)
                   case string: fmt.Printf(“param #%d is a string\n”, i)
                    default: fmt.Printf(“param #%d’s type is unknown\n”, i)
            }
}

8.类型断言,采用type switch方式

switch t := areaIntf.(type) {case *Square:        fmt.Printf(“Type Square %T with value %v\n”, t, t) 
case *Circle:       fmt.Printf(“Type Circle %T with value %v\n”, t, t) 
case float32:       fmt.Printf(“Type float32 with value %v\n”, t)case nil:        fmt.Println(“nil value: nothing to check?”) 
default:        fmt.Printf(“Unexpected type %T”, t)}

9.空接口,Interface{} 空接口没有任何方法,所以所有类型都实现了空接口。

var a int
var b interface{}
b  = a

10.判断一个变量是否实现了指定接口 判断一个变量是否实现了指定接口

 type Stringer interface {
        String() string 
}
var v MyStruct
if sv, ok := v.(Stringer); ok {
       fmt.Printf(“v implements String(): %s\n”, sv.String()); 
} 

package main

import "fmt"

//没有方法的空接口,任何类型都可以
type Test interface {}

func main() {
	var a interface{}
	a = 666
	fmt.Println(a)
	fmt.Printf("a的类型是:%T", a)
}

输出: 666 a的类型是:int Process finished with exit code 0

package main

import "fmt"

//接口里的方法必须全部实现!
type Carer interface {
	GetName() string
	Run()
	DiDi()
}

type BMW struct {
	Name string
}

func (p *BMW) GetName() string {
	return p.Name
}

func (p *BMW) Run() {
	fmt.Printf("%s is running\n", p.Name)
}

func (p *BMW) DiDi() {
	fmt.Printf("%s is didi\n", p.Name)
}

func main() {
	var car Carer
	//如果接口中的方法只声明不实现,则是nil
	//fmt.Println(car)
	//不实现Run方法而调用会报错
	//car.Run()
	var bmw BMW
	bmw.Name = "x6"
	//因为struct BMW是指针类型,所以bmw要引用传递
	car = &bmw
	car.Run()
}

输出: x6 is running

Process finished with exit code 0 也可以值传递:

package main

import "fmt"

//接口里的方法必须全部实现!
type Carer interface {
	GetName() string
	Run()
	DiDi()
}

type BMW struct {
	Name string
}

func (p BMW) GetName() string {
	return p.Name
}

func (p BMW) Run() {
	fmt.Printf("%s is running\n", p.Name)
}

func (p BMW) DiDi() {
	fmt.Printf("%s is didi\n", p.Name)
}

func main() {
	var car Carer
	//如果接口中的方法只声明不实现,则是nil
	//fmt.Println(car)
	//不实现Run方法而调用会报错
	//car.Run()
	var bmw BMW
	bmw.Name = "x6"
	//值类型传递也是可以的,上面的p *BMW也要换成p BMW
	car = bmw
	car.Run()
}

应用实例: go语言的sort包是用接口方式写的,可以轻松的自定义:

package main

import (
	"fmt"
	"math/rand"
	"sort"
)

type Student struct {
	Name string
	Id string
	Age int
}

type Book struct {
	Name string
	Author string
}

//切片默认就是传地址的,所以不需要在方法中用*
type studentArray []Student

func (p studentArray) Len() int {
	return len(p)
}

func (p studentArray) Less(i, j int) bool {
	return p[i].Name < p[j].Name
}

func (p studentArray) Swap(i, j int) {
	p[i], p[j] = p[j], p[i]
}

func main() {
	var stus studentArray
	for i := 0; i < 5; i++ {
		stu := Student{
			Name: fmt.Sprintf("stu%d", rand.Intn(100)),
			Id: fmt.Sprintf("100%d", rand.Int()),
			Age: rand.Intn(100),
		}
		stus = append(stus, stu)
	}
	for _, v := range stus {
		fmt.Println(v)
	}

	fmt.Println("")

	//调用sort包进行排序(stus中用自带的方法)
	sort.Sort(stus)

	for _, v := range stus {
		fmt.Println(v)
	}
}

输出: {stu81 1008674665223082153551 47} {stu59 1003916589616287113937 18} {stu25 1001443635317331776148 56} {stu0 1004751997750760398084 11} {stu62 1003510942875414458836 28}

{stu0 1004751997750760398084 11} {stu25 1001443635317331776148 56} {stu59 1003916589616287113937 18} {stu62 1003510942875414458836 28} {stu81 1008674665223082153551 47}

Process finished with exit code 0

类型断言实例:

package main

import "fmt"

func main()  {
	var a interface{}
	fmt.Printf("%T\n", a)
	var b int
	a = b
	c := a.(int)
	fmt.Printf("%T\n", a)
	fmt.Printf("%T\n", c)
}

输出: <nil> int int

Process finished with exit code 0

package main

import "fmt"

func duanYan(a interface{}) {
	//int(a)是数据类型的转换,这是接口转成具体类
	b, ok := a.(int)
	if ok == false {
		fmt.Println("转换失败")
		return
	}
	b += 3
	fmt.Println(b)
}

func main()  {
	//b是int型则转换成功,string型转换失败
	var b int
	duanYan(b)
}

输出: 3

Process finished with exit code 0

package main

import "fmt"

type Student struct {
	Name string
	Sex  string
}

func Test(a interface{}) {
	b, ok := a.(Student)
	if ok == false {
		fmt.Println("convert failed")
		return
	}
	//b += 3
	fmt.Println(b)
}

func just(items ...interface{}) {
	for index, v := range items {
		switch v.(type) {
		case bool:
			fmt.Printf("%d params is bool, value is %v\n", index, v)
		case int, int64, int32:
			fmt.Printf("%d params is int, value is %v\n", index, v)
		case float32, float64:
			fmt.Printf("%d params is float, value is %v\n", index, v)
		case string:
			fmt.Printf("%d params is string, value is %v\n", index, v)
		case Student:
			fmt.Printf("%d params student, value is %v\n", index, v)
		case *Student:
			fmt.Printf("%d params *student, value is %v\n", index, v)
		}
	}
}

func main() {
	var b Student = Student{
		Name: "stu01",
		Sex:  "female",
	}
	Test(b)
	just(28, 8.2, "this is a test", b, &b)
}

输出: {stu01 female} 0 params is int, value is 28 1 params is float, value is 8.2 2 params is string, value is this is a test 3 params student, value is {stu01 female} 4 params *student, value is &{stu01 female}

Process finished with exit code 0