Golang学习笔记(8)

面向对象编程思想

面向对象编程思想-抽象

我们在定义一个结构体时,实际上就是把一类事物的共有的属性(字段)和行为(方法)七区出来,形成一个物理模型(模板)。这种研究问题的方法称为抽象。

package main

import "fmt"

type Account struct {
	AccountNo string
	Pwd       string
	Balance   float64
}

func (account *Account) Deposit(money float64, pwd string) {
	//比对输入的密码是否正确
	if pwd != account.Pwd {
		fmt.Println("输入的密码错误")
		return
	}
	//看判断存款金额是否正确
	if money <= 0 {
		fmt.Println("输入的金额错误")
		return
	}
	account.Balance += money
	fmt.Println("存款成功")
}

// 取款
func (account *Account) WithDraw(money float64, pwd string) {
	//比对输入的密码是否正确
	if pwd != account.Pwd {
		fmt.Println("输入的密码错误")
		return
	}
	//看判断存款金额是否正确
	if money <= 0 || money > account.Balance {
		fmt.Println("输入的金额错误")
		return
	}
	account.Balance -= money
	fmt.Println("取款成功")
}

// 查询余额功能
func (account *Account) Query(pwd string) {
	//比对输入的密码是否正确
	if pwd != account.Pwd {
		fmt.Println("输入的密码错误")
		return
	}
	fmt.Printf("你的账号为 = %v 余额 = %v ", account.AccountNo, account.Balance)
}
func main() {
	//测试
	account := &Account{
		AccountNo: "gs111111",
		Pwd:       "666666",
		Balance:   100.0,
	}
	account.Query("666666")
	account.Deposit(100.0, "666666")
	account.Query("666666")
}

面向对象的三大特征

基本介绍

Golang仍然有面向对象编程的继承、封装和多态的特性,只是实现的方式和其它OOP语言不同。

面向对象编程-封装

封装介绍

封装(encapsulation)就是把抽象出的字段和对字段的操作封装在一起,数据呗保护在内部,程序的其他包只有通过被授权的操作(方法),才能对字段进行操作。

封装的理解和好处

  1. 隐藏现实细节
  2. 可以对数据进行验证,保证安全合理

如何体现封装

  1. 对结构体中的属性进行封装
  2. 通过方法、包,进行封装

封装的实现步骤

  1. 将结构体、字段(属性)的首字母小写(不能导出了,其它包不能使用,类似private)
  2. 给结构体所在包提供一个工厂模式的函数,首字母大写。类似一个构造函数
  3. 提供一个首字母大写的Set方法(类似其它语言的public),用于对属性判断并赋值
    func (var 结构体类型名)SetXxx(参数列表)(返回值列表){
    //加入数据验证的业务逻辑
    var.字段=参数
    }
  4. 提供一个首字母大写的Get方法(类似其它语言的public),用于获取属性的值
    func (var 结构体类型名)GetXxx(参数列表)(返回值列表){
    return var.字段
    }
    案例:创建一个程序(person.go),不能随便查看人的年龄,工资等隐私,并对输入的年龄进行合理的验证
package model

import "fmt"

type person struct {
	Name string
	age  int //其它包不能直接访问
	sal  float64
}

// 写一个工厂模式函数,相当于构造函数
func NewPerson(name string) *person {
	return &person{
		Name: name,
	}
}

// 为了访问age 和 sal编写一对SetXxx方法和GetXxx方法
func (p *person) SetAge(age int) {
	if age > 0 && age < 150 {
		p.age = age
	} else {
		fmt.Println("年龄范围不正确..")
		//有程序员给一个默认值
	}
}
func (p *person) GetAge() int {
	return p.age
}
func (p *person) SetSal(sal float64) {
	if sal >= 3000 && sal < 30000 {
		p.sal = sal
	} else {
		fmt.Println("薪水范围不正确..")
		//有程序员给一个默认值
	}
}
func (p *person) GetSal() float64 {
	return p.sal
}



package main

import (
	"fmt"
	"go_code/chapter11/model"
)

func main() {
	p := model.NewPerson("smith")
	p.SetAge(18)
	p.SetSal(18000)
	fmt.Println(p)
	fmt.Println(p.Name)
	fmt.Println(p.GetAge())
	fmt.Println(p.GetSal())
}

创建程序,在model包中定义Account结构体,在main函数中体会Golang的封装性
Account结构体要求具有字段:账号(长度在6-10之间)、余额(必须>20)、密码(必须是六位数)
通过SetXxx的方法给Account的字段赋值
在main函数中测试

package model

import "fmt"

type account struct {
	accountNo string
	pwd       string
	balance   float64
}

func NewAccount(accountNo string, pwd string, balance float64) *account {
	if len(accountNo) < 6 || len(accountNo) > 10 {
		fmt.Println("账号的长度不对...")
		return nil
	}

	if len(pwd) != 6 {
		fmt.Println("密码长度不对...")
		return nil
	}

	if balance < 20 {
		fmt.Println("余额数目不对...")
		return nil
	}
	return &account{
		accountNo: accountNo,
		pwd:       pwd,
		balance:   balance,
	}
}
func (a *account) GetAccountNO() string {
	return a.accountNo
}
func (a *account) SetPwd(pwd string) bool {
	if len(pwd) != 6 {
		fmt.Println("密码需要6位")
		return false
	} else {
		a.pwd = pwd
		return true
	}
}
func (a *account) GetPwd() string {
	return a.pwd
}

func (account *account) Deposit(money float64, pwd string) {
	//比对输入的密码是否正确
	if pwd != account.pwd {
		fmt.Println("输入的密码错误")
		return
	}
	//看判断存款金额是否正确
	if money <= 0 {
		fmt.Println("输入的金额错误")
		return
	}
	account.balance += money
	fmt.Println("存款成功")
}

// 取款
func (account *account) WithDraw(money float64, pwd string) {
	//比对输入的密码是否正确
	if pwd != account.pwd {
		fmt.Println("输入的密码错误")
		return
	}
	//看判断存款金额是否正确
	if money <= 0 || money > account.balance {
		fmt.Println("输入的金额错误")
		return
	}
	account.balance -= money
	fmt.Println("取款成功")
}

// 查询余额功能
func (account *account) Query(pwd string) {
	//比对输入的密码是否正确
	if pwd != account.pwd {
		fmt.Println("输入的密码错误")
		return
	}
	fmt.Printf("你的账号为 = %v 余额 = %v ", account.accountNo, account.balance)
}






package main

import (
	"fmt"
	"go_code/demo/model"
)

func main() {

	account := model.NewAccount("jzh11111", "999999", 10000.0)
	if account != nil {
		fmt.Println("创建成功=", account)
	} else {
		fmt.Println("创建失败")
	}
	account.SetPwd("123456")
	fmt.Println(account)
	account.Deposit(10, "123456")
	account.Query("123456")

	account.WithDraw(8000, "123456")
	account.Query("123456")

}

面向对象编程-继承

继承的基本介绍

继承可以解决代码复用,让我们的编程更加接近人类思维
当多个结构体存在相同的属性(字段)和方法是,也已从这些结构体中抽象出结构体,在该结构体中定义这些相同的属性和方法。
其它的结构体不需要重新定义这些属性和方法,只需要嵌套一个匿名结构体即可。
也就是说:在Golang中,如果一个struct嵌套了另一个匿名结构体,那么这个结构体可以直接访问匿名结构体的字段和方法,从而实现了继承特性。

嵌套匿名结构体的基本语法

type Goods struct{
Name string
Price int
}
type Book struct{
Goods //这里就是嵌套匿名结构体Goods
Writer string
}

继承的案例

package main

import "fmt"

// 编写一个学生考试系统
type Student struct {
	Name  string
	Age   int
	Score int
}

func (stu *Student) ShowInfo() {
	fmt.Printf("学生名=%v,年龄=%v,成绩=%v\n", stu.Name, stu.Age, stu.Score)
}
func (stu *Student) SetScore(score int) {
	stu.Score = score
}

type Pupil struct {
	Student
}

func (p *Pupil) testing() {
	fmt.Println("小学生正在考试中...")
}

type Graduate struct {
	Student
}

func (p *Graduate) testing() {
	fmt.Println("大学生正在考试中...")
}
func main() {
	//当我们对结构体嵌入了匿名结构体后,使用的方法会发生变化
	pupil := &Pupil{}
	pupil.Student.Name = "tom"
	pupil.Student.Age = 8
	pupil.testing()
	pupil.Student.SetScore(80)
	pupil.Student.ShowInfo()
	graduate := Graduate{}
	graduate.Student.Name = "jack"
	graduate.Student.Age = 21
	graduate.testing()
	graduate.Student.SetScore(90)
	graduate.Student.ShowInfo()
}

继承的深入讨论

  1. 结构体可以使用嵌套匿名结构体所有的字段和方法,即:首字母大写或者小写的字段、方法,都可以使用
package main

import "fmt"

type A struct {
	Name string
	age  int
}

func (a *A) SayOk() {
	fmt.Println("A SayOk", a.Name)
}
func (a *A) hello() {
	fmt.Println("A hello", a.Name)
}

type B struct {
	A
}

func main() {
	var b B
	b.A.Name = "tom"
	b.A.age = 19
	b.A.SayOk()
	b.A.hello()
}

  1. 匿名结构体字段访问可以简化
func main() {
	var b B
	b.Name = "tom"
	b.age = 19
	b.SayOk()
	b.hello()
}

(1)当我们直接通过b访问字段或方法时,执行流程如下,如b.Name
(2)编译器会先看b对应的类型有没有Name,如果有,直接调用B类型的Name字段
(3)如果没有直接看B中嵌入的匿名结构体A中有没有声明Name,如果有就调用,如果没有就继续查找,如果都找不到,就报错

  1. 当结构体和匿名结构体有相同的字段或者方法是,编译器采用就近访问原则访问,如希望访问匿名结构体的字段和方法,可以通过匿名结构体名来区分。
  2. 结构体嵌入两个(或多个)匿名结构图,图两个匿名结构体有相同的字段和方法(同时结构体本身没有同名的字段和方法),在访问时,就必须明确匿名结构体的名字,否则报错。
package main

import "fmt"

type A struct {
	Name string
	age  int
}
type B struct {
	Name string
	age  int
}
type C struct {
	A
	B
	Name string
}

func main() {
	var c C
	//如果c没有Name字段,而A和B有Name,这时就必须通过指定匿名字段来区分
	c.Name = "tom"
	fmt.Println("c", c)
}

  1. 如果一个struct嵌套了一个有名结构体,这种模式就是组合,如果是组合关系,那么在访问组合的结构体字段或方法时,必须带上结构体的名字。
type D struct{
	a A //有名结构体(组合关系)
}
func main (){
	var d D
	d.a.Name = "jack"
}
  1. 嵌套匿名结构体后,也可以创建结构体变量(实例)时,直接指定各个匿名结构体字段的值。
package main

import "fmt"

type Goods struct {
	Name  string
	Price float64
}
type Brand struct {
	Name    string
	Address string
}
type TV struct {
	Goods
	Brand
}
type TV2 struct {
	*Goods
	*Brand
}

func main() {
	tv := TV{Goods{"电视机001", 5000.99}, Brand{"海尔", "山东"}}
	tv2 := TV{
		Goods{
			Price: 5000.00,
			Name:  "电视机002",
		},
		Brand{
			Name:    "夏普",
			Address: "北京",
		},
	}
	fmt.Println("tv", tv)
	fmt.Println("tv2", tv2)
	tv3 := TV2{&Goods{"电视机003", 7000.99}, &Brand{"创维", "河南"}}
	tv4 := TV2{
		&Goods{
			"电视机004",
			8000.99,
		},
		&Brand{
			"TCL",
			"上海",
		},
	}
	fmt.Println("tv3", *tv3.Goods, *tv3.Brand)
	fmt.Println("tv4", *tv4.Goods, *tv4.Brand)
}

结构体的匿名字段是基本数据类型,如何访问
type Monster struct{
	Name string
	Age int
}
type E struct {
	Monster
	int 
	n int
}
func main(){
	var e E 
	e.Name = "狐狸精"
	e.Age = 300
	e.int = 20
	e.n = 40
	fmt.Println("e = ",e)
}

说明

  1. 如果一个结构体有int类型的匿名字段,就不能有第二个
  2. 如果需要有多个int字段,则必须给int字段指定名称

多重继承

说明

如一个struct嵌套了多个匿名结构体,那么该结构体可以直接访问嵌套的匿名结构体的字段和方法,从而实现了多重继承。

细节说明

  1. 如嵌入的匿名结构体有相同的字段名或者方法名,则在访问时,需要通过匿名结构体类型名来区分
  2. 为了保证代码的简洁性,建议尽量不要使用多重继承

接口(interface)

基本介绍

interface类型可以定义一组方法,但是这些方法不需要实现,并且interface不能包含任何变量。到某个自定义类型(比如结构体Phone)要使用时,在根据具体情况把这些方法写出来。

基本语法

type 接口名 interface{
method1(形参列表)返回值列表
method2(形参列表)返回值列表

}
实现接口所有方法
func(t 自定义类型)method1(形参列表)返回值列表{
//方法实现
}
func(t 自定义类型)method2(形参列表)返回值列表{
//方法实现
}
说明:

  1. 接口里的所有方法都没有方法体,即接口的方法都是没有实现的方法,接口体现了程序设计的多态和高内聚低耦合的思想
  2. Golang中的接口,不需要显示的实现,只要一个变量,含有接口类型中的所有方法,那么这个变量就实现这个接口。因此,Golang中没有implement这样的关键字。

注意事项和细节

  1. 接口本身不能创建实例,但是可以指向一个实现了该接口的自定义类型的变量(实例)
  2. 接口中所有的方法都没有方法体,即都是没有实现的方法。
  3. 在Golang中,一个自定义类型需要将某个接口的所有方法都实现,我们说这个自定义类型实现了该接口。
  4. 一个自定义类型只有实现了某个接口,才能将该自定义类型的实例(变量)赋给接口类型。
  5. 只要是自定义数据类型,就可以实现接口,不仅仅是结构体类型。
  6. 一个自定义类型可以实现多个接口
  7. Golang接口中不能有任何变量
  8. 一个接口,可以继承多个别的接口,这事如果要是先A接口,也必须将B,C接口的方法也全部实现。
  9. interface类型默认是一个指针(引用类型),如果没有对interface初始化使用,那么会输出nil
  10. 空接口interface{}没有任何方法,所以所有类型都实现了空接口 ,即我们可以把任何变量赋给空接口。
type T interface{
}
func main(){
	var t T = stu
	fmt.Println(t)
	var t2 interface{} = stu
	var num1 float64 = 8.8
	t2 = num1
	t = num1
	fmt.Println(t2,t) 
}
接口的实践

实现对hero结构体切片的排序 sort_Sort(data Interface)

package main

import (
	"fmt"
	"math/rand"
	"sort"
)

type Hero struct {
	Name string
	Age  int
}
type HeroSlice []Hero

// 实现接口
func (s HeroSlice) Len() int {
	return len(s)
}

// less决定使用什么标准进行排序
func (s HeroSlice) Less(i, j int) bool {
	return s[i].Age < s[j].Age
}
func (s HeroSlice) Swap(i, j int) {
	//temp := s[i]
	//s[i] = s[j]
	//s[j] = temp
	s[i],s[j] = s[j],s[i]
}
func main() {
	var intSlice = []int{1, -1, 10, 7, 29}
	sort.Ints(intSlice)
	fmt.Println(intSlice)
	//测试
	var heroes HeroSlice
	for i := 0; i < 10; i++ {
		hero := Hero{
			Name: fmt.Sprintf("英雄%d", rand.Intn(100)),
			Age:  rand.Intn(100),
		}
		heroes = append(heroes, hero)
	}
	for _, v := range heroes {
		fmt.Println(v)
	}
	sort.Sort(heroes)
	fmt.Println("--------排序后--------")
	for _, v := range heroes {
		fmt.Println(v)
	}
}

  • 将Student的切片,按照Score从大到小排序
package main

import (
	"fmt"
	"math/rand"
	"sort"
)

type Student struct {
	Name  string
	Age   int
	Score float64
}
type StudentSlice []Student

func (stu StudentSlice) Len() int {
	return len(stu)
}
func (stu StudentSlice) Less(i, j int) bool {
	return stu[i].Score > stu[j].Score
}
func (stu StudentSlice) Swap(i, j int) {
	stu[i], stu[j] = stu[j], stu[i]
}
func main() {
	var stu StudentSlice
	for i := 0; i < 10; i++ {
		student := Student{
			Name:  fmt.Sprintf("学生的名字%d", rand.Intn(100)),
			Age:   rand.Intn(100),
			Score: float64(rand.Intn(100)),
		}
		stu = append(stu, student)
	}
	for _, v := range stu {
		fmt.Println(v)
	}
	sort.Sort(stu)
	fmt.Println("------排序后------")
	for _, v := range stu {
		fmt.Println(v)
	}
}

实现接口与继承

package main

import "fmt"

// Monkey结构体
type Monkey struct {
	Name string
}

// 声明接口
type BirdAble interface {
	Flying()
}
type FishAble interface {
	Swimming()
}

func (this *Monkey) climbing() {
	fmt.Println(this.Name, "生来会爬树...")
}

// littleMonkey 结构体
type littleMonkey struct {
	Monkey
}

// 让littleMonkey实现BirdAble
func (this *littleMonkey) Flying() {
	fmt.Println(this.Name, "通过学习,会飞了...")
}
func (this *littleMonkey) Swimming() {
	fmt.Println(this.Name, "通过学习,会游泳了...")
}
func main() {
	monkey := littleMonkey{
		Monkey{
			Name: "孙悟空",
		},
	}
	monkey.climbing()
	monkey.Flying()
}

  • 总结
  1. 当A结构体继承了B结构体,那么A结构就自动的继承了B结构体的字段和方法,并且可以直接使用
  2. 当A结构体需要扩展功能,同时不希望去破坏继承关系,则可以去实现某个接口即可,因此我们可以认为,实现接口是对继承机制的补充。
  • 实现接口可以看作是对继承的一种补充
  • 接口和继承解决的问题不同
    继承的价值主要在于:解决代码的复用性和可维护性
    接口的价值主要在于:设计,设计好各种规范(方法),让其它自定义类型去实现这些方法
  • 接口比继承更加灵活
    接口比继承更加灵活,继承是满足is-a的关系,而接口只需满足like-a的关系。
  • 接口在一定程度上实现代码解耦

面向对象编程-多态

基本介绍

变量(实例)具有多种形态。面向对象的第三大特征,在Go语言,多态特征是通过接口实现的,可以按照统一的接口来调用不用的实现,这时接口变量就呈现不同的形态。

package main

import "fmt"

//声明一个接口
type Usb interface {
	//声明两个没有实现的方法
	Start()
	Stop()
}
type Phone struct {
}

//让结构体实现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("相机停止工作")
}

type Computer struct {
}

//Working方法接收一个Usb接口类型变来给你
//主要是实现Usb接口(所谓实现Usb接口,就是值实现了Usb接口声明的所有方法)
func (c Computer) Working(usb Usb) {
	//通过usb接口变量来调用start和atop方法
	usb.Start()
	usb.Stop()
}
func main() {
	//创建结构体变量
	computer := Computer{}
	phone := Phone{}
	camera := Camera{}

	computer.Working(phone)
	computer.Working(camera)
}

接口体现多态的两种特征

  1. 多态参数
    在Usb接口案例中,Usb usb,即可以接收手机变量,又可以接收相机变量,就体现了Usb接口多态
  2. 多态数组
    演示一个案例:给Usb数组中,存放Phone结构体和Camera结构体变量,Phone还有一个特有的方法call(),请遍历Usb数组,如果是Phone变量,除了调用Usb接口声明的方法外,还需要调用Phone特有方法call。
package main

import "fmt"

type Usb interface {
	//声明两个没有实现的方法
	Start()
	Stop()
}
type Phone struct {
	name string
}

// 让结构体实现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{"vivo"}
	usbArr[1] = Phone{"小米"}
	usbArr[2] = Camera{"尼康"}

	fmt.Println(usbArr)
}

类型断言

基本介绍
类型断言,由于接口是一般类型,不知道具体类型,如果要转成具体类型,就需要使用类型断言:

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
	b = a.(Point)
	fmt.Println(b)

	var x interface{}
	var b2 float32 = 1.1
	x = b2 //空接口可以接收任意类型
	//x=>float32
	y := x.(float32)
	fmt.Printf("y的类型是%T 值是 = %v", y, y)
}
  • 对上面代码的说明:
    在进行类型断言时,如果类型不匹配会报paic,因此进行类型断言时,要确保原来的空接口指向的就是要断言的类型。
  • 如何在进行短延时,带上监测机制,如果成果就OK,否则也不报panic
//带检测的类型断言

	var x interface{}
	var b2 float32 = 1.1
	x = b2 //空接口可以接收任意类型
	//x=>float32

	if y, ok := x.(float32); ok {
		fmt.Println("convert success")
		fmt.Printf("y的类型是%T 值是 = %v\n", y, y)
	} else {
		fmt.Println("convert fail")
	}
	fmt.Println("继续执行...")
package main

import "fmt"

type Usb interface {
	//声明两个没有实现的方法
	Start()
	Stop()
}
type Phone struct {
	name string
}

// 让结构体实现Usb接口的方法
func (p Phone) Start() {
	fmt.Println("手机开始工作")
}
func (p Phone) Stop() {
	fmt.Println("手机停止工作")
}
func (p Phone) Call() {
	fmt.Println("手机开始打电话..")
}

type Camera struct {
	name string
}

// 让Camera实现usb接口的方法
func (c Camera) Start() {
	fmt.Println("相机开始工作")
}
func (c Camera) Stop() {
	fmt.Println("相机停止工作")
}

type Computer struct {
}

func (computer Computer) Working(usb Usb) {
	usb.Start()
	//usb是指向Phone结构体变量,调用call方法
	//类型断言
	if phone, ok := usb.(Phone); ok {
		phone.Call()
	}
	usb.Stop()
}
func main() {
	//定义一个Usb接口数组,可以存放Phone和Camera的结构体变量
	//这里体现出多态数组
	var usbArr [3]Usb
	usbArr[0] = Phone{"vivo"}
	usbArr[1] = Phone{"小米"}
	usbArr[2] = Camera{"尼康"}
	//遍历usbArr
	var computer Computer
	for _, v := range usbArr {
		computer.Working(v)
		fmt.Println()
	}

}

  • 写一个函数,循环判断传入参数的类型
package main

import (
	"fmt"
)

// 编写一个函数,可以判断输入的参数是什么类型
func TypeJudge(items ...interface{}) {
	for index, x := range items {
		switch x.(type) {
		case bool:
			fmt.Printf("第%v个参数是bool类型,值是%v\n", index, x)
		case float32:
			fmt.Printf("第%v个参数是float32类型,值是%v\n", index, x)
		case float64:
			fmt.Printf("第%v个参数是float64类型,值是%v\n", index, x)
		case int, int32, int64:
			fmt.Printf("第%v个参数是整数类型,值是%v\n", index, x)
		case string:
			fmt.Printf("第%v个参数是bool类型,值是%v\n", index, x)
		default:
			fmt.Printf("第%v个参数类型不支持,值是%v\n", index, x)

		}
	}
}

func main() {
	var n1 float32 = 1.1
	var n2 float64 = 2.3
	var n3 int32 = 30
	var name string = "Tyler Bennett"
	address := "北京"
	n4 := 300
	TypeJudge(n1, n2, n3, name, address, n4)

}

增加判断Student类型和*Student类型

package main

import (
	"fmt"
)

// 编写一个函数,可以判断输入的参数是什么类型
func TypeJudge(items ...interface{}) {
	for index, x := range items {
		switch x.(type) {
		case bool:
			fmt.Printf("第%v个参数是bool类型,值是%v\n", index, x)
		case float32:
			fmt.Printf("第%v个参数是float32类型,值是%v\n", index, x)
		case float64:
			fmt.Printf("第%v个参数是float64类型,值是%v\n", index, x)
		case int, int32, int64:
			fmt.Printf("第%v个参数是整数类型,值是%v\n", index, x)
		case string:
			fmt.Printf("第%v个参数是bool类型,值是%v\n", index, x)
		case Student:
			fmt.Printf("第%v个参数是Student类型,值是%v\n", index, x)
		case *Student:
			fmt.Printf("第%v个参数是*Student类型,值是%v\n", index, x)

		default:
			fmt.Printf("第%v个参数类型不支持,值是%v\n", index, x)

		}
	}
}

type Student struct {
}

func main() {
	var n1 float32 = 1.1
	var n2 float64 = 2.3
	var n3 int32 = 30
	var name string = "Tyler Bennett"
	address := "北京"
	n4 := 300
	stu1 := Student{}
	stu2 := &Student{}

	TypeJudge(n1, n2, n3, name, address, n4, stu1, stu2)

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值