定义

基本语法

  1. type 接口名 interface {
  2. method1(参数列表) 返回值列表
  3. method2(参数列表) 返回值列表
  4. }

例子:多态

  1. type Animal interface {
  2. Eat()
  3. Drink()
  4. }
  5. type Dog struct {
  6. }
  7. func (X Dog) Eat(){
  8. fmt.Println("狗爱吃骨头")
  9. }
  10. func (X Dog) Drink(){
  11. fmt.Println("狗爱喝骨头汤" )
  12. }
  13. type Cat struct {
  14. }
  15. func (J Cat) Eat(){
  16. fmt.Println("猫爱吃鱼")
  17. }
  18. func (J Cat) Drink(){
  19. fmt.Println("猫爱喝鱼汤")
  20. }
  21. type Person struct {
  22. }
  23. func (P *Person) Feed(A Animal) {
  24. A.Eat()
  25. A.Drink()
  26. }
  27. func main() {
  28. p :=Person{}
  29. d :=Dog{}
  30. c :=Cat{}
  31. p.Feed(d)
  32. p.Feed(c)
  33. }
  34. //------------------
  35. 如果DogCat绑定方法时,用的是指针
  36. func (X *Dog) Eat(){
  37. fmt.Println("狗爱吃骨头")
  38. }
  39. 那么在main方法中,在调用时
  40. p.Feed(d)应改为p.Feed(&d),否则语法不通过
  41. 原因:一个变量实现了某个接口后,在接口内部不能获取到该变量的地址(不可寻址)
  42. 所以在p.Feed时,就需要传一个地址过去

注意事项

  • 接口只定义方法名,不能有方法体
  • 接口中不能有变量
  • 接口的实现:一个变量实现了接口所有的方法(当然它还可以有自己的方法),那么称这个变量实现了该接口
  • 只要是自定义数据类型都可以实现接口,不一定要是结构体
  • 一个自定义类型可以实现多个接口
  • 一个接口A,如果继承了其他的接口B,C。在实现A时,必须将B,C中的方法也实现。同时也需要注意,B,C中没有相同的方法,否则A接口的方法重复定义
  • 任何类型都实现了空接口

    sort.Sort(data Interface)

    ```go

    Student中的Score进行升序排列

    type Student struct { Name string Age int Score float64 }

type Students []Student

func (S Students) Len() int{ return len(S) } func (S Students) Less(i, j int) bool{ return S[i].Score<S[j].Score } func (S Students) Swap(i, j int){ S[i],S[j]=S[j],S[i] } func main() { S :=Student{} var SS Students rand.Seed(time.Now().UnixNano()) for i:=1;i<=5;i++{ S.Name=fmt.Sprintf(“小明%v号”,i) S.Age=rand.Intn(30) S.Score=float64(rand.Intn(100)) SS=append(SS,S) } fmt.Println(SS)//[{小明1号 20 44} {小明2号 13 39} {小明3号 3 79} {小明4号 28 18} {小明5号 8 27}] sort.Sort(SS) fmt.Println(SS)//[{小明4号 28 18} {小明5号 8 27} {小明2号 13 39} {小明1号 20 44} {小明3号 3 79}] }

  1. <a name="Tpdl1"></a>
  2. #
  3. <a name="DSLpY"></a>
  4. # 断言
  5. <a name="EQ4Uw"></a>
  6. ### 用法
  7. ```go
  8. func main() {
  9. var a interface{}
  10. b :=11.11
  11. a=b//空接口类型的值可以接受任意类型的值
  12. if c,flag:=a.(float64); flag{
  13. fmt.Println(c)
  14. }else {
  15. fmt.Println("转型失败!!!")
  16. }
  17. }

断言实践:多态

  1. type Animal interface {
  2. Eat()
  3. Drink()
  4. }
  5. type Dog struct {
  6. }
  7. func (X Dog) Eat(){
  8. fmt.Println("狗爱吃骨头")
  9. }
  10. func (X Dog) Drink(){
  11. fmt.Println("狗爱喝骨头汤" )
  12. }
  13. func (X Dog) Call(){
  14. fmt.Println("狗:汪汪汪" )
  15. }
  16. type Cat struct {
  17. }
  18. func (J Cat) Eat(){
  19. fmt.Println("猫爱吃鱼")
  20. }
  21. func (J Cat) Drink(){
  22. fmt.Println("猫爱喝鱼汤")
  23. }
  24. type Person struct {
  25. }
  26. func (P *Person) Feed(A Animal) {
  27. A.Eat()
  28. A.Drink()
  29. if b,flag :=A.(Dog);flag{
  30. b.Call()
  31. }//如果不检验,由于Cat中没有Call(),会编译不通过
  32. }
  33. func main() {
  34. var arr =[...]Animal{
  35. Dog{},
  36. Cat{},
  37. }
  38. P :=Person{}
  39. for _,v :=range arr{
  40. P.Feed(v)
  41. }
  42. }

断言实践:类型判断

  1. type Student2 struct {
  2. }
  3. func Judge(items ...interface{}){
  4. for i,v :=range items{
  5. i++
  6. switch v.(type) {
  7. case int,int8,int16,int32,int64:
  8. fmt.Printf("第%v个参数的类型是--int\n",i)
  9. case float64,float32:
  10. fmt.Printf("第%v个参数的类型是--float\n",i)
  11. case bool:
  12. fmt.Printf("第%v个参数的类型是--bool\n",i)
  13. case string:
  14. fmt.Printf("第%v个参数的类型是--string\n",i)
  15. case *Student2:
  16. fmt.Printf("第%v个参数的类型是--*Student2\n",i)
  17. case Student2:
  18. fmt.Printf("第%v个参数的类型是--Student2\n",i)
  19. default:
  20. fmt.Printf("第%v个参数的类型不确定\n",i)
  21. }
  22. }
  23. }
  24. func main() {
  25. a:=1
  26. b:=1.0
  27. c:=true
  28. d:="旺财"
  29. e:=&Student2{}
  30. f:=Student2{}
  31. g :=make([]int,10)
  32. Judge(g,a,b,c,d,e,f)
  33. }

空接口的陷阱

  • 在使用空接口做为数据类型时,在使用时一定要还原
    1. type Cat struct {
    2. Name string
    3. Age string
    4. }
    5. func main() {
    6. slice :=make([]interface{},3)
    7. slice[0]=1
    8. slice[1]="哈哈"
    9. slice[2]=Cat{"小花","10"}
    10. fmt.Println(slice)
    11. c :=slice[2]
    12. //a :=slice[0]
    13. //a++ 基本数据类型也需要断言
    14. //fmt.Println(c.Name) 编译不通过
    15. newc,flag:=c.(Cat)
    16. if !flag{
    17. panic("断言失败")
    18. }
    19. fmt.Println(newc.Name)//小花
    20. }

判断有没实现接口

  1. type Printer interface {
  2. Print()
  3. }
  4. type Java struct {
  5. }
  6. func (j Java) SystemOut() {
  7. fmt.Println("java")
  8. }
  9. type Golang struct {
  10. }
  11. func (g Golang) Print() {
  12. fmt.Println("golang")
  13. }
  14. func main() {
  15. var g Golang
  16. //var j Java
  17. run111(g)
  18. }
  19. func run111(i interface{}) {
  20. if p, ok := i.(Printer); ok {
  21. p.Print()
  22. } else {
  23. fmt.Println("未实现Printer接口")
  24. }
  25. }