package main
import (
"fmt"
)
// 定义一个 Usb 接口
type Usb interface{
Start()
Stop()
}
// 定义手机结构体
type Phone struct{
}
// 让Phone实现Usb接口的方法
func (p Phone) Start(){
fmt.Println("手机正在启动中......")
}
func (p Phone) Stop(){
fmt.Println("手机正在关闭中......")
}
// 定义相机结构体
type Camera struct{
}
// 让Camera实现Usb接口的方法
func (c Camera) Start(){
fmt.Println("相机正在启动中......")
}
func (c Camera) Stop(){
fmt.Println("相机正在关闭中......")
}
// 定义一个Computer结构体
type Computer struct{
}
// 编写一个Working方法,接收一个Usb接口类型变量
// 只要是实现了Usb接口(所谓实现Usb接口,就是指实现了Usb接口声明的所有方法)
func (c Computer) Working(usb Usb) { // usb变量会根据传入的实参,来判断到底是Phone还是Camera
// 通过usb接口变量来调用Start和Stop方法
usb.Start()
usb.Stop()
}
func main() {
// 测试,先创建结构体变量
phone := Phone{}
camera := Camera{}
computer := Computer{}
computer.Working(phone)
//手机正在启动中......
//手机正在关闭中......
computer.Working(camera)
//相机正在启动中......
//相机正在关闭中......
}
interface类型可以定义一组方法,但是这些不需要实现。并且interface不能包含任何变量。到某个自定义类型(比如结构体Phone)要使用的时候,在根据具体情况把这些方法写出来(实现)。
基本语法:
// 定义接口类型
type 接口名 interface{
method1(参数列表) 返回值列表
method2(参数列表) 返回值列表
...
}
// 实现接口所有方法
func (t 自定义类型) method1(参数列表) 返回值列表 {
// 方法实现
}
func (t 自定义类型) method2(参数列表) 返回值列表 {
// 方法实现
}
...
说明:
多态
和高内聚低耦合
的思想。implement
这样的关键字。package main
import (
"fmt"
)
type AInterface interface {
Say()
}
type Student struct {
Name string
}
func (stu Student) Say() {
fmt.Println("stu Say()")
}
func main() {
var stu Student
var a AInterface = stu
a.Say() // stu Say()
}
type integer int
func (i integer) Say() {
fmt.Println("integer i Say() =", i)
}
func main() {
var i integer = 10
var b AInterface = i
b.Say() // integer i Say() = 10
}
type AInterface interface {
Say()
}
type BInterface interface{
Hello()
}
type Monster struct{
}
func (m Monster) Hello(){
fmt.Println("Monster hello")
}
func (m Monster) Say(){
fmt.Println("Monster Say")
}
func main() {
var a2 AInterface = Monster
var b2 BInterface = Monster
a2.Say() // Monster Say
b2.Hello() //Monster hello
}
type AInterface interface{
Name string // 错误的写法
Test01()
Test02()
}
package main
import (
"fmt"
)
type BInterface interface {
test01()
}
type CInterface interface {
test02()
}
type AInterface interface {
BInterface
CInterface
test03()
}
type Student struct {
}
func (stu Student) test01(){
fmt.Println("stu test01()......")
}
func (stu Student) test02(){
fmt.Println("stu test02()......")
}
func (stu Student) test03(){
fmt.Println("stu test02()......")
}
func main() {
var stu Student
var a AInterface = stu
a.test01() // stu test01()......
a.test02() // stu test02()......
a.test03() // stu test03()......
}
type T interface{
}
type Student struct {
Name string
}
func (stu Student) Say() {
fmt.Println("stu Say()")
}
func main() {
var stu Student
var t T = stu
fmt.Println(t)
var t2 interface{} = stu
var num1 float64 = 8.8
t2 = num1
t = num1
fmt.Println(t2, t)
}
实现对结构体切片的排序 sort.Sort(data Interface)
package main
import (
"fmt"
"sort"
"math/rand"
)
// (1)声明一个Hero结构体
type Hero struct {
Name string
Age int
}
// (2)声明一个Hero结构体的切片类型
type HeroSlice []Hero
// (3)实现Interface接口
func (hs HeroSlice) Len() int {
return len(hs)
}
// Less方法就是决定使用什么标准进行排序
func (hs HeroSlice) Less(i, j int) bool {
// 如果i 排在j前面,那么返回true
return hs[i].Age > hs[j].Age
}
func (hs HeroSlice) Swap(i, j int) {
hs[i], hs[j] = hs[j], hs[i]
}
func main() {
var intSlice = []int{13, 1, -1, 0, 15, 56}
//对切片进行排序
sort.Ints(intSlice)
fmt.Println(intSlice) // [-1 0 1 13 15 56]
//对结构体切片进行排序
var heroes HeroSlice
for i := 0; i < 10; i++{
hero := Hero{
Name : fmt.Sprintf("英雄~%d", rand.Intn(100)),
Age : rand.Intn(100),
}
// 将hero append到heroes切片
heroes = append(heroes, hero)
}
// 排序前 遍历切片
for _, v := range(heroes){
fmt.Println("排序前", v)
}
// 调用sort.Sort
sort.Sort(heroes)
for _, v := range(heroes){
fmt.Println("排序后", v)
}
}
package main
import "fmt"
type BirdFly interface {
Flying()
}
// 定义一个Monkey猴子结构体
type Monkey struct {
Name string
}
func (m *Monkey) Climbing() {
fmt.Println(m.Name, "天生会爬树...")
}
type LittleMonkey struct {
Monkey // 继承
}
func (m *LittleMonkey) Flying() {
fmt.Println(m.Name, "通过后天学习,会飞翔了....")
}
func main() {
monkey := LittleMonkey{
Monkey{
Name : "孙悟空",
},
}
monkey.Climbing() // 孙悟空 天生会爬树...
monkey.Flying()
}
变量(实例)具有多种形态。面向对象的第三大特征,在Go语言中,多态特征是通过接口实现的。可以按照统一的接口来调用不同的实现。这时接口变量就呈现不同的形态。
在下边的Usb 的案例就是多态的体现,usb Usb,既可以接收手机变量,又可以接收相机变量,就体现了Usb接口多态特性
package main
import (
"fmt"
)
// 定义一个 Usb 接口
type Usb interface{
Start()
Stop()
}
// 定义手机结构体
type Phone struct{
Name string
}
// 让Phone实现Usb接口的方法
func (p Phone) Start(){
fmt.Println("手机正在启动中......")
}
func (p Phone) Stop(){
fmt.Println("手机正在关闭中......")
}
// 定义相机结构体
type Camera struct{
Name string
}
// 让Camera实现Usb接口的方法
func (c Camera) Start(){
fmt.Println("相机正在启动中......")
}
func (c Camera) Stop(){
fmt.Println("相机正在关闭中......")
}
func main() {
// 定义一个Usb接口数组,可以存放Phone和Camera的结构体变量
// 这里就体现出多态数组
var usbArr [3]Usb
usbArr[0] = Phone{"apple"}
usbArr[1] = Phone{"华为"}
usbArr[2] = Camera{"Nikon"}
fmt.Println(usbArr) // [{apple} {华为} {Nikon}]
}
断言引出:如何将一个接口变量类型,赋值给自定义类型的变量
package main
import "fmt"
type Point struct {
x int
y int
}
func main() {
var a interface{}
var point Point = Point{1, 2}
a = point
var b Point
// 此时如果想让a赋值给b,不能直接 b = a
// 要用类型断言
b = a.(Point)
// 表示判断a是否是指向Point类型的变量,如果是就转成Point类型并赋给b变量,否则就报错
fmt.Println(b) // 输出 {1, 2}
// 类型断言的其它案例
var a1 interface{}
var b1 float64 = 1.1
a1 = b1
y := a1.(float64) // 这边就不能写 a1.(float32)
fmt.Println(y)
// 在进行类型断言时,如果类型不匹配,就会报panic错误
// 如何在进行断言时,带上监测机制,如果成功就ok,否则也不要报panic
var x interface{}
var b2 float64 = 1.1
x = b2
b2, ok := x.(float32)
if ok { // ok为true
fmt.Println("转换成功......")
fmt.Printf("b2 的类型是%T 值是%v", b2, b2)
} else {
fmt.Println("转换失败")
}
// 上边的判断可以简写为
// if b2, ok := x.(float32); ok {}
fmt.Println("继续执行")
}
在之前USB实例做改进,给Phone结构体增加一个特有的方法call(),当Usb接口接收的是Phone变量时,还需要调用call方法
package main
import (
"fmt"
)
type Usb interface {
Start()
Stop()
}
// 定义手机结构体
type Phone struct {
Name string
}
func (p *Phone) Start() {
fmt.Println("Phone正在启动中......")
}
func (p *Phone) Stop() {
fmt.Println("Phone正在关闭中......")
}
func (p *Phone) Call() {
fmt.Println("Phone正在打电话")
}
// 定义相机结构体
type Camera struct {
Name string
}
func (c *Camera) Start() {
fmt.Println("Camera正在启动中......")
}
func (c *Camera) Stop() {
fmt.Println("Camera正在关闭中......")
}
type Computer struct {
}
func (c *Computer) Working(usb Usb) {
usb.Start()
// 如果usb指向Phone结构体变量,则还需要调用Call方法
// 类型断言
if phone, ok := usb.(*Phone); ok {
phone.Call()
}
usb.Stop()
}
func main() {
var usbArr [3]Usb
usbArr[0] = &Phone{"vivo"}
usbArr[1] = &Phone{"小米"}
usbArr[2] = &Camera{"Nikon"}
var computer Computer
for _, v := range usbArr {
computer.Working(v)
fmt.Println()
}
// fmt.Println(usbArr)
}
package main
import (
"fmt"
)
type Student struct {
}
// 写一个函数,循环判断传入参数的类型
func JudgeType(items... interface{}) {
for index, x := range items {
switch x.(type) { // 这里type是一个关键字,固定写法
case bool:
fmt.Printf("第%v个参数是 bool 类型,值是 %v \n", index + 1, x)
case float64, float32:
fmt.Printf("第%v个参数是 浮点类型 类型,值是 %v \n", index + 1, x)
case int, int32, int64:
fmt.Printf("第%v个参数是 整型 类型,值是 %v \n", index + 1, x)
case string:
fmt.Printf("第%v个参数是 string 类型,值是 %v \n", index + 1, x)
case Student :
fmt.Printf("第%v个参数是 Student 类型,值是 %v \n", index + 1, x)
case *Student :
fmt.Printf("第%v个参数是 *Student 类型,值是 %v \n", index + 1, x)
default:
fmt.Println("第%v个参数是 类型不确定,值是 %v \n", index + 1, x)
}
}
}
func main() {
var n1 float32 = 1.1
var n2 float64 = 2.2
var n3 int = 10
var str string = "Hello"
stu := Student{}
stu1 := &Student{}
JudgeType(n1, n2, n3, str, stu, stu1)
}
/*
第1个参数是 浮点类型 类型,值是 1.1
第2个参数是 浮点类型 类型,值是 2.2
第3个参数是 整型 类型,值是 10
第4个参数是 string 类型,值是 Hello
第5个参数是 Student 类型,值是 {}
第6个参数是 *Student 类型,值是 &{}
*/