go语言基础语法:面向对象编程

一、匿名组合

1.匿名字段初始化

type Person struct {
	name string
	sex  byte
	age  int
}
type Student struct {
	Person//只有类型,没有名字,匿名字段,继承了Person里面的成员
	id   int
	addr string
}

func main() {
//顺序初始化
	var s1 Student = Student{Person{"mike", 'm', 18}, 1, "bj"}
	fmt.Println("s1=", s1)
//自动推导类型
	s2 := Student{Person{"mike", 'm', 18}, 1, "bj"}
	fmt.Println("s2=", s2)
//%+v,显示更详细
	fmt.Printf("s2=%+v\n", s2)
//指定成员初始化,没有初始化的成员自动赋值为0
	s3 := Student{Person: Person{name: "mike"}, id: 1}
	fmt.Printf("s3=%+v\n", s3)
}

2.成员的操作

Person和Student结构体成员的定义如上

    var s1 Student = Student{Person{"mike", 'm', 18}, 1, "bj"}
	s1.name = "yoyo"
	s1.sex = 'f'
	s1.age = 22
	s1.id = 2
	s1.addr = "sz"
	fmt.Printf("s1=%+v\n", s1)
	s1.Person = Person{"go", 'm', 18}
	fmt.Println(s1.name, s1.sex, s1.age, s1.id, s1.addr)

3.同名字段

Person结构体的定义如上

type Student struct {
	Person
	id   int
	addr string
	name string//与Person中的字段同名了
}

func main() {
//声明一个变量
	var s Student
//默认规则(就近原则),如果能在本作用域找到此成员,就操作此成员
//如果没有找到,就找继承的字段
	s.name = "mike"
	s.sex = 'm'
	s.age = 18
	s.addr = "bj"
	fmt.Printf("s=%+v\n", s)
//显式调用
	s.Person.name = "yoyo"//指明给Person的name赋值
	fmt.Printf("s=%+v\n", s)
}

4.非结构体匿名字段

Person结构体定义如上

type mystr string//自定义类型,给一个类型改名
type Student struct {
	Person//结构体匿名字段
	int   //基础类型的匿名字段(非结构体匿名字段)
	mystr
}

func main() {
	s := Student{Person{"mike", 'm', 18}, 1, "bj"}
	fmt.Printf("s=%+v\n", s)
	s.Person = Person{"go", 'm', 22}
	fmt.Println(s.name, s.age, s.sex, s.int, s.mystr)
	fmt.Println(s.Person, s.int, s.mystr)
}

5.结构体指针类型匿名字段

type Student struct {
	*Person//指针类型
	id   int
	addr string
}

func main() {
	s1 := Student{&Person{"mike", 'm', 18}, 1, "bj"}
	fmt.Printf("s1=%+v\n", s1)//Person部分显式的是地址
	fmt.Println(s1.name, s1.sex, s1.age, s1.id, s1.addr)
//先定义变量
	var s2 Student
	s2.Person = new(Person)//new一下,分配空间
	s2.name = "yoyo"
	s2.sex = 'f'
	s2.age = 22
	s2.id = 2
	s2.addr = "sz"
	fmt.Println(s2.name, s2.sex, s2.age, s2.id, s2.addr)
}

二、方法

1.面向过程和对象函数的区别

//面向过程
func Add01(a, b int) int {
	return a + b
}

type long int
//面向对象,方法:给某个类型绑定一个函数
//tmp叫接收者,接收者就是传递的一个参数
func (tmp long) Add02(other long) long {
	return tmp + other
}
func main() {
	var result int
	result = Add01(1, 1)//普通函数调用方式
	fmt.Println("result=", result)
//定义一个变量
	var a long = 2
//调用方法格式:变量名.函数(所需函数)
	res := a.Add02(3)
	fmt.Println("res=", res)
//面向对象只是换了一种表现形式
}

2.为结构体类型添加方法

Person结构体定义如上

//带有接收者的函数叫做方法
func (tmp Person) PrintInfo() {
	fmt.Println("tmp=", tmp)
}
//通过一个函数给成员赋值
func (tmp *Person) SetInfo(n string, s byte, a int) {
	tmp.name = n
	tmp.sex = s
	tmp.age = a
}

type long int
//只要接收者类型不同,即使方法同名也是不同的方法,不属于重复定义
func (tmp long) test() {}

type char byte

func (tmp char) test() {}

type pointer *int
//pointer是指针,接收者类型本身不能是指针,接收者类型不能是指针
//func (tmp pointer) test() {}
func main() {
	p := Person{"mike", 'm', 18}
	p.PrintInfo()
	var p2 Person
	(&p2).SetInfo("yoyo", 'f', 22)
	p2.PrintInfo()
}

3.值语义和引用

Person结构体的定义如上

//修改成员变量的值
//参数为普通变量,非指针,值语义,一份拷贝
func (p Person) SetInfoValue(n string, s byte, a int) {
	p.name = n
	p.sex = s
	p.age = a
	fmt.Println("p=", p)
	fmt.Printf("SetInfoValue &p=%p\n", &p)
}
//接收者为指针变量,引用传递
func (p *Person) SetInfoPointer(n string, s byte, a int) {
	p.name = n
	p.sex = s
	p.age = a
	fmt.Printf("SetInfoPointer p=%p\n", p)
}
func main() {
	var s1 Person = Person{"go", 'm', 22}
	fmt.Printf("&s1=%p\n", &s1)
//值语义
	s1.SetInfoValue("mike", 'm', 18)
	fmt.Printf("s1=%+v\n", s1)
//引用语义
	(&s1).SetInfoPointer("mike", 'm', 18)
	fmt.Printf("s1=%+v\n", s1)
}

4.指针变量的方法集

Person结构体定义如上

func (p Person) SetInfoValue() {
	fmt.Println("SetInfoValue")
}
func (p *Person) SetInfoPointer() {
	fmt.Println("SetInfoPointer")
}
func main() {
//结构体变量是一个指针变量
//它能够调用哪些方法,这些方法就是一个集合
//简称方法集
	p := &Person{"mike", 'm', 18}
	(*p).SetInfoPointer()
	p.SetInfoPointer()
	p.SetInfoValue()
	(*p).SetInfoValue()
//p和*p之间互相转化,然后调用方法
}

5.普通变量的方法集

func (p Person) SetInfoValue() {
	fmt.Println("SetInfoValue")
}
func (p *Person) SetInfoPointer() {
	fmt.Println("SetInfoPointer")
}
func main() {
	p := Person{"mike", 'm', 18}
	p.SetInfoPointer()
//内部先将p转为&p再调用,(&p).SetInfoPointer
	p.SetInfoValue()
}

6.方法的继承

Person和Student结构体定义如上

//Person类型实现了一个方法
func (tmp *Person) PrintInfo() {
	fmt.Printf("name=%s,sex=%c,age=%d\n", tmp.name, tmp.sex, tmp.age)
}
type Student struct{
    Person
    id int
    sddr string
}
func main() {
//学生继承了Person字段,成员和方法都继承了
	s := Student{Person{"mike", 'm', 18}, 1, "bj"}
	s.PrintInfo()
}

7.方法的重写

Person和Student的结构体定义如上

func (tmp *Person) PrintInfo() {
	fmt.Printf("name=%s,sex=%c,age=%d\n", tmp.name, tmp.sex, tmp.age)
}
//Student也实现了一个方法,这个方法和Person中的方法同名,这种叫做方法的重写
func (tmp *Student) PrintInfo() {
	fmt.Println("Student:tmp=", tmp)
}
func main() {
	s := Student{Person{"mike", 'm', 18}, 1, "bj"}
//就近原则,先找本作用域的方法,找不到再找继承的方法
	s.PrintInfo()
//显示调用继承的方法
	s.Person.PrintInfo()
}

8.方法值

func (p Person) SetInfoValue() {
	fmt.Printf("SetInfoValue:%p,%v\n", &p, p)
}
func (p *Person) SetInfoPointer() {
	fmt.Printf("SetInfoPointer:%p,%v\n", p, *p)
}
func main() {
	s := Person{"mike", 'm', 18}
	fmt.Printf("main:%p,%v", &s, s)
	s.SetInfoPointer()//传统调用方式
//保存方法入口地址
	sFunc := s.SetInfoPointer
//这个就是方法值,调用函数时,无需再传递接收者,隐藏了接收者
	sFunc()
	vFunc := s.SetInfoValue
	vFunc()//等价于s.SetInfoValue()
}

9.方法表达式

Person结构体定义如上

func (p Person) SetInfoValue() {
	fmt.Printf("SetInfoValue:%p,%v\n", &p, p)
}
func (p *Person) SetInfoPointer() {
	fmt.Printf("SetInfoPointer:%p,%v\n", p, *p)
}
func main() {
	p := Person{"mike", 'm', 18}
	fmt.Printf("main:%p,%v\n", &p, p)
	//方法值 f:=p.SetInfoPointer//隐藏了接收者
	//方法表达式
	f := (*Person).SetInfoPointer
	f(&p) //显示把接收者传递过去====》p.SetInfoPointer()
	f2 := (Person).SetInfoValue
	f2(p) //显示把接收者传递过去====》p.SetInfoValue()
}

三、接口

1.接口的定义和实现

type Humaner interface {
//方法,只有声明,没有实现,由别的类型(自定义类型)实现
	sayHi()
}
type Student struct {
	name string
	id   int
}

func (tmp *Student) sayHi() {
	fmt.Printf("Student[%s,%d] say hi\n", tmp.name, tmp.id)
}

type Teacher struct {
	addr  string
	group string
}

func (tmp *Teacher) sayHi() {
	fmt.Printf("Teacher[%s,%s] say hi\n", tmp.addr, tmp.group)
}

type Mystr string

func (tmp *Mystr) sayHi() {
	fmt.Printf("Mystr[%s] say hi", *tmp)
}
func main() {
//定义接口类型变量
	var i Humaner
//只要实现了此接口方法的类型,那么这个类型的变量(接收者类型)就可赋值
	s := &Student{"mike", 1}
	i = s
	i.sayHi()
	t := &Teacher{"bj", "go"}
	i = t
	i.sayHi()
	var str Mystr = "hello"
	i = &str
	i.sayHi()
}

2.多态

在1的基础上,添加代码

//定义一个普通函数,函数的参数为接口类型
//只有一个函数,但可以有不同表现,多态
func WhoSayHi(i Humaner) {
	i.sayHi()
}
func main() {
	s := &Student{"mike", 1}
	t := &Teacher{"bj", "go"}
	var str Mystr = "hello"
//调用同一函数,实现不同表现,称为多态
	WhoSayHi(s)
	WhoSayHi(t)
	WhoSayHi(&str)
//创建一个切片
	x := make([]Humaner, 3)
	x[0] = s
	x[1] = t
	x[2] = &str
//第一个返回下标,第二个返回下标所对应的值
	for _, i := range x {
		i.sayHi()
	}
}

3.接口的继承

type Humaner interface {//子集
	sayhi()
}
type personer interface {//超集
	Humaner//匿名字段,继承了sayhi()方法
	sing(lrc string)
}
type Student struct {
	name string
	id   int
}

func (tmp *Student) sayhi() {
	fmt.Printf("Student[%s,%d] say hi\n", tmp.name, tmp.id)
}
func (tmp *Student) sing(lrc string) {
	fmt.Println("Student在唱:", lrc)
}
func main() {
//定义一个接口类型的变量
	var i personer
	s := &Student{"mike", 1}
	i = s
	i.sayhi()//继承过来的方法
	i.sing("lalala")
}

4.接口转换

接口,结构体,方法定义如上

    //超集可以转换为子集,反过来不行
    var iPro Personer//超集
	iPro = &Student{"mike", 1}
	var i Humaner//子集
	//iPro=i//err
	i = iPro
	i.sayhi()

5.空接口

//空接口万能类型,保存任意类型的值
    var i interface{} = 1
	fmt.Println("i=", i)
	i = "abc"
	fmt.Println("i=", i)

6.类型断言:if

type Student struct {
	name string
	id   int
}

func main() {
	i := make([]interface{}, 3)
	i[0] = 1
	i[1] = "hello"
	i[2] = Student{"mike", 1}
    //类型查询,类型断言
	for index, data := range i {
        //第一个返回的是值,第二个返回判断结果的真假
		if value, ok := data.(int); ok == true {
			fmt.Printf("x[%d]类型为int,内容为%d\n", index, value)
		} else if value, ok := data.(string); ok == true {
			fmt.Printf("x[%d]类型为string,内容为%s\n", index, value)
		} else if value, ok := data.(Student); ok == true {
			fmt.Printf("x[%d]类型为Student,内容为name=%s,id=%d\n", index, value.name, value.id)
		}
	}
}

7.类型断言:switch

func main() {
	i := make([]interface{}, 3)
	i[0] = 1
	i[1] = "hello"
	i[2] = Student{"mike", 1}
	for index, data := range i {
		switch value := data.(type) {//value还是值
		case int:
			fmt.Printf("x[%d]类型为int,内容为%d\n", index, value)
		case string:
			fmt.Printf("x[%d]类型为string,内容为%s\n", index, value)
		case Student:
			fmt.Printf("x[%d]类型为Student,内容为name=%s,id=%d\n", index, value.name, value.id)
		}
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值