- 接口
- 多态
- 结构体里的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]
<nil>
<nil>
*/
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)
}
}
网友评论