golang学习笔记第三部分:12.golang的面向对象编程1

golang学习笔记第三部分:12.golang的面向对象编程1

23、go的面向”对象“编程

1、结构体

自定义数据类型,支持方法定义。go语言面向对象编程特性的实现。 结构体是值类型。 声明: type 名称 struct { field1 type field2 type }

  • 名称首字母大写,可以被其他包引用,小写是私有
  • 字段可以是基础类型,也可以是引用类型
  • 字段类型是指针、切片、map时,默认值是nil,使用前需要先make,因为结构体是值类型,字段是引用类型时,默认并没有分配内存空间
  • 不同结构体变量的字段是独立的,相互不影响
  • 结构体的所有字段在内存中是连续的,可以通过数据类型长度加减直接操作内存读取数据
  • 结构体是用户自定义的类型,和其他类型转换时需要有完全相同的字段(名称、数量、类型)
  • 结构体进行type重新定义,golang认为是新的数据类型,拥有相同的字段信息
  • 在结构体的每个字段上,可以写一个tag,该tag可以通过反射机制获取,常见的场景是序列化和反序列化,比如json ;还有在gorm等库中,也是利用到tag

2、方法

  • 方法是数据的行为
  • golang的方法是作用在指定的数据类型上的,因此自定义类型都可以有方法,而不仅仅是struct
  • 方法的声明 func (receiver type) methodName(参数列表) (返回值列表){ 方法体 return 返回值 }
  • receiver方法和type类型绑定,receiver类似python的self,java的this,实际开发中常规写法(cat Cat)
  • 方法的调用 var a1 A // 实例化 a1.test() // 只能通过A类型的实例调用
  • 方法的调用、传参机制和函数基本一样,区别是方法调用时,会将调用方法的实例,当做实参也传递给方法,注意结构体类型的方法是值传递
  • 在开发中,为了避免值传递,提高效率,方法常绑定结构体指针
  • 如果一个类型实现了String()方法,那么fmt.Println打印时,会默认输出String()方法
  • 声明方法时的绑定方式,决定了是值传递还是引用传递(receiver type);(receiver *type)
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.Printf("存款%v成功!\n", money)
}

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.Printf("取款%v成功!\n", money)
}

func (account *Account) Query(pwd string) {
	//行为:查询余额
	if pwd != account.Pwd {
		fmt.Println("密码输入错误!")
		return
	}
	fmt.Printf("账号%v的余额为%v\n", account.AccountNo, account.Balance)
}

func main() {
	Tangshan := Account{
		AccountNo: "1001",
		Pwd:       "123",
		Balance:   100.00,
	}
	Tangshan.Deposit(100, "123")
	Tangshan.WithDraw(200, "123")
	Tangshan.Query("123")
}

3、go面向对象编程一

  • 声明结构体,确定名称
  • 编写字段
  • 编写结构体的方法
  • 创建结构体时指定字段值:
    1)有几种方式,
    var a type = type{按顺序写入每个字段值};
    var b type = type{ field1 : value1, field2 : value2, } // 注意逗号
    2)建议使用第二种方式,理由是第一种方式在结构体字段修改后,很容易由于顺序改变而出现类型错误
  • 返回结构体指针:var a = &type{参考上面2种写法};a := &type{xxx}
package main

import "fmt"

type PUpi1 struct {
	Name  string
	Age   int
	Score int
}

func (u *PUpi1) ShowInfo() {
	fmt.Printf("学生名=%v 年龄=%v 成绩%v\n", u.Name, u.Age, u.Score)
}

// SetScore 嵌入匿名结构体,称为继承,如果命名,则称为组合
func (u *PUpi1) SetScore(score int) {
	u.Score = score
}

// testing
func (u *PUpi1) testing() {
	fmt.Println("1 stu testing")
}

// GUtil 嵌入匿名结构体
type GUtil struct {
	PUpi1
	Skill string
}

// testing 即使方法名相同,那也是2个不同结构体的,相互不影响
func (u *GUtil) testing() {
	fmt.Println("2 stu testing")
}

func main() {
	var pupil = PUpi1{
		Name: "james",
		Age:  10,
	}
	pupil.testing()
	pupil.SetScore(90)
	pupil.ShowInfo()

	var g1 = GUtil{}
	g1.Name = "tom" // 等同于gutil.PUpil.Name
	g1.Age = 20
	g1.testing()
	g1.SetScore(90)
	g1.ShowInfo()
	pupil.testing()

	var g2 = GUtil{
		PUpi1: PUpi1{ // 嵌入匿名结构体赋值时,需要带上引用
			Name:  "g2",
			Age:   18,
			Score: 99,
		},
		Skill: "song",
	}
	g2.ShowInfo()

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值