接口声明

// 接口声明 语法:接口是一个 函数签名 的集合,函数签名(函数的声明,不包括实现)
type  interfaceName interface {
        method1(param paramType, param paramType...) (returnName returnType ...)
        method2(param paramType, param paramType...) (returnName returnType ...)
}


// 接口名一般加  er
type writer interface {
   write(num int) (n int, flag bool)
   cache(p []byte) int
}
// 若方法名首字母是大写时,且接口名首字母也是大写时,这个方法可以被接口所在的包(package)之外的代码访问。


// 声明结构体
type structName struct {
  filed1 filedType
  filed2 filedType
}


// 实现接口中的方法
func (structVariableName structName) method1 (param paramType, param paramType...) (returnName returnType returName returnType, ...) {
  // do something
}

func (structVairableName structName) method2 (param paramType, param paramType...) (returnName returnType, returnName returnType,...) {
  // do something
}

// 参数列表、返回值列表:参数列表和返回值列表中的参数变量名可以被忽略



// 实例
type Phone interface {
   call(number int) string
}

// 定义结构体
type Apple struct {
   name string
}

type Sony struct {
   name string
}
// 实现方法
func (appleBanner Apple) call(number int) string {
   fmt.Println("param number: ", number)
   fmt.Println("banner name: ", appleBanner.name)
   return "successful"
}

func (sonyBanner Sony) call(number int) string {
   fmt.Println("param number: ", number)
   fmt.Println("banner name: ", sonyBanner.name)
   return "successful"
}

func main() {
  var apple = Apple{"apple"}
  apple.call(1031)

  sony := Sony{"sony"}
  sony.call(313)
} 

 

 

 

 

实现接口的条件

  • 接口中的方法签名包括:方法名称、方法所需参数、参数类型、方法的返回值、返回值类型;若需要实现接口中的某个方法签名,其上述的五个要点需全部保持一致。
  • 接口被正确的编译使用需要 实现接口中的全部方法

 

 

 

 

类型与接口、接口与接口

  • 一个类型可以实现多个接口,比如一个 socket 结构体同时实现了 io接口和日志接口。
  • 多个类型可以实现相同的接口 ,一个结构体可以嵌套另一个结构体,若一个接口有多个方法需要实现,可以某个结构体实现其中几个方法,剩下的方法由另一个结构体实现。
// 包含 开启方法和写日志方法 的服务接口
type Service interface {
    Start()  // 开启服务
    Log(string)  // 日志输出
}

// 日志器
type Logger struct {
}

// 日志结构体 实现 Log()方法
func (g *Logger) Log(l string) {
}

// 游戏服务
type GameService struct {
    Logger  // 嵌入日志器
}

// 游戏结构体 Start()方法
func (g *GameService) Start() {
}


// 使用
var s Service = new(GameService)
s.Start()
s.Log(“hello”)

 

 

  • 一个接口同时包含了多个其他接口,产生了一个新的接口
// 写入接口
type Writer interface {
   Write(p []byte) (n int, err error)}
// 关闭接口
type Closer interface {
     Close() error
}


// 接口嵌套
type Logger interface {    // 此接口需要两个接口嵌入
        Writer  
        Closer
}   

 

 

 

 

排序接口

 

 

 

 

package main

import (
    "fmt"
    "sort"
)

// 自定义类型 排序
type Interface interface {
    Len() int                    // 序列内元素数量
    Less(i, j int) bool        // 序列中 索引为i的元素 < 索引为j的元素
    Swap(i , j int)            // 交换两个索引上的元素
}

// 将字符串定义成 自定义类型 (type 关键字)
type MyStringList []string        // []string:  字符串切片; 为了能对自定义的字符串切片排序,需要让 MyStringList 实现 Interface 接口

// 方法
func (stringLists MyStringList) Len() int {
    return len(stringLists)
}

func (stringLists MyStringList) Less(i, j int) bool {
    return stringLists[i] < stringLists[j]
}

func (stringLists MyStringList) Swap(i, j int) {
    stringLists[i], stringLists[j] = stringLists[j], stringLists[i]
}



// 结构体排序
type HeroKind int                    // 英雄的种类
const (                                // 定义 HeroKind 的 value 为常量, 类似枚举
    None HeroKind = iota
    Tank
    Assassin
    Mage
)

type Hero struct {                  // 定义英雄的结构
    Name string                         // 英雄名字
    Kind HeroKind                  // 英雄种类
}

type Heros []*Hero             // 英雄切片集合
// 实现 Interface 接口的三个方法
func (heros Heros) Len() int {
    return len(heros)
}

func (heros Heros) Less(i, j int) bool {
    if heros[i].Kind != heros[j].Kind {            // 两个英雄的种类不一致时, 优先的按照 种类数字大小进行对比, 否则 则按照英雄名字对比
        return heros[i].Kind < heros[j].Kind
    }
    return heros[i].Name < heros[j].Name
}

func (heros Heros) Swap(i, j int) {
    heros[i], heros[j] = heros[j], heros[i]
}



// 对切片元素进行排序: sort.Slice()


func main() {
    // 1、自定义类型实现排序
    names := MyStringList {
        "3. Triple Kill",
        "5. Penta Kill",
        "2. Double Kill",
        "4. Quadra Kill",
        "1. First Blood",
    }
    fmt.Println(names)
    sort.Sort(names)                // 排序:sort.Interface 用于指定 通用排序算法 和 可能被排序到的序列类型 之间的规定
    fmt.Println(names)


    // 2、sort 包中的便捷排序
    //names := sort.StringSlice {            // 字符串切片 排序
    //    "3. Triple Kill",
    //    "5. Penta Kill",
    //    "2. Double Kill",
    //    "4. Quadra Kill",
    //    "1. First Blood",
    //}
    //fmt.Println(names)
    //sort.Strings(names)
    //fmt.Println(names)

    //nums := sort.IntSlice {                // 整型切片 排序
    //    10,
    //    1,
    //    6,
    //    5,
    //    2,
    //}
    //fmt.Println(nums)
    //sort.Ints(nums)
    //fmt.Println(nums)

    //doubles := sort.Float64Slice{            // 双精度小数切片 排序
    //    5.02,
    //    3.31,
    //    10.19,
    //    2.20,
    //    12.12,
    //    6.18,
    //    1.12,
    //}
    //fmt.Println(doubles)
    //sort.Float64s(doubles)
    //fmt.Println(doubles)


    // 3、结构体排序
    heros := Heros{
        &Hero{"吕布", Tank},
        &Hero{"李白", Assassin},
        &Hero{"妲己", Mage},
        &Hero{"貂蝉", Assassin},
        &Hero{"关羽", Tank},
        &Hero{"诸葛亮", Mage},
    }
    fmt.Println("排序前结构体顺序: ")
    for index, hero := range heros {
        fmt.Print(index, "\t")
        fmt.Println(*hero)
    }

    //sort.Sort(heros)


    // 4、对切片元素排序: sort.Slice(slice interface{}, less func(i, j int) bool) {...}
    sort.Slice(heros, func(i, j int) bool {            // 传入 切片 和 在排序时对元素进行判断的回调函数
        if heros[i].Kind != heros[j].Kind {
            return heros[i].Kind < heros[j].Kind
        }
        return heros[i].Name < heros[j].Name
    })

fmt.Println()
for index, hero := range heros { fmt.Print(index, "\t") fmt.Println(*hero) } }

 

 posted on 2019-11-04 17:25  lin-gooo  阅读(275)  评论(0编辑  收藏  举报