go得快(1)

  • 接口
  • 多态
  • 结构体里的tag
  • 类型断言
  • 空接口
  • 接口的三个规则
package main

import (
    "fmt"
    "strconv"
    //"encoding/json"
    //"reflect"
)




type Phone interface {
    call()
}
type Apple struct {
    name string
}
//如果有一个类型/结构体,实现了一个接口要求的所有方法,这里 Phone 接口只有 call方法,所以只要实现了 call 方法,我们就可以称它实现了 Phone 接口。
func(iphone Apple) call(){
    fmt.Print("我是iphone")
}




type Good interface {
    setAmount() int
    showInfo() string
}

type House struct {
    name string
    price int
    quantity int
}
func (house House) setAmount() int{
    return house.quantity * house.price
}
func (house House) showInfo() string{
    return "购买了" + strconv.Itoa(house.quantity) + "套房子,一共" + strconv.Itoa(house.price)
}

type Car struct {
    name string
    price int
    quantity int
}
func (car Car) setAmount() int{
    return 0
}
func (car Car) showInfo() string{
    return "半买半送了" + strconv.Itoa(car.quantity) + "辆车,一共" + strconv.Itoa(car.price)
}




type Language interface {
    code()
}
type Php struct {
    Name string
}

func (l Php)code()  {
    fmt.Println(l.Name)
}
func (l Php)connect()  {
    fmt.Println("php connect")
}




func main(){
    //step1 Apple结构体实现了接口
    ii := Apple{name: "苹果手机"}
    ii.call()
    fmt.Print("\n\n")


    //step2 接口实现多态,买房送半价车子。这个也能叫多态,规定了有setAmount() showInfo()方法的就叫商品,所以别墅和小车都算商品了
    hh := House{name: "别墅", quantity: 1, price: 100000}
    cc := Car{name: "小车", quantity: 1, price: 100}

    goods := []Good{hh, cc}
    for _ , good := range goods{
        fmt.Println(good.showInfo())
    }
    fmt.Print("\n\n")


    //step3 结构体里的tag
    //可以利用反射,知道结构体里tag的属性值(可以当默认值使用)


    //step4 类型断言,其实就是类型的判断
    var i interface{} = 10
    t1 := i.(int)
    fmt.Println(t1)

    //t2 := i.(string)//触发 panic 报错
    //fmt.Println(t2)//触发 panic 报错

    //如果需要不报错,可以这样
    t2, ok := i.(string)
    fmt.Printf("%s - %t", t2, ok) //输出 “ - false”
    fmt.Print("\n\n")

    fmt.Printf("type: %T, value: %v", i, i) //利用自带的可以解析出值和值的类型
    fmt.Print("\n\n")

    //step5 空接口
    //5.1通常我们会直接使用 interface{} 作为类型声明一个实例,而这个实例可以承载任意类型的值。
    var i1 interface{}
    // 存 int 没有问题
    i1 = 1
    fmt.Println(i1)
    // 存字符串也没有问题
    i1 = "hello"
    fmt.Println(i1)
    // 存布尔值也没有问题
    i1 = false
    fmt.Println(i1)
    fmt.Print("\n\n")


    //5.2 函数可以接收任意类型的值 ,也可以使用空接口
    a1 := 10
    b1 := "接收任意个任意类型的值"
    c1 := true

    myfunc(a1, b1, c1)
    fmt.Print("\n\n")


    //5.3 定义一个可以接收任意类型的 array、slice、map、strcut,例如这边定义一个切片
    any := make([]interface{}, 5)
    any[0] = 11
    any[1] = "接收任意类型的 array、slice、map、strcut"
    any[2] = []int{11, 22, 33, 44}
    for _, value := range any {
        fmt.Println(value)
    }
    /*
    输出:
        11
        接收任意类型的 array、slice、map、strcut
        [11 22 33 44]
        
        
    */
    fmt.Print("\n\n")


    //step6 接口的三个“潜规则”
    //6.1 接口有方法A,结构体有A和B方法,如果显示的声明了对象是接口的,则不能调用方法B,否则可以
    //var onel Language //加上这个就不能调用connect方法了
    onel := Php{Name: "php"}
    onel.code()
    onel.connect()
    fmt.Print("\n\n")

    //6.2 接口类型的显示转换
    a12 := 10
    switch interface{}(a12).(type) {
        case int:
            fmt.Println("参数的类型是 int")
        case string:
            fmt.Println("参数的类型是 string")
    }
    fmt.Print("\n\n")


    //6.3 类型断言中的隐式转换
    //静态类型为接口类型的对象才可以进行类型断言
    //而当类型断言完成后,会返回一个静态类型为你断言的类型的对象,也就是说,当我们使用了类型断言,Go 实际上又会默认为我们进行了一次隐式的类型转换。
    //验证方法也很简单,使用完一次类型断言后,对返回的对象再一次使用类型断言,Goland 立马就会提示我们新对象 b 不是一个接口类型的对象,不允许进行类型断言。




}


func myfunc(ifaces ...interface{}){
    for _,iface := range ifaces{
        fmt.Println(iface)
    }
}

你可能感兴趣的:(go得快(1))