Golang语言面向对象编程(上)冰乐

1、Golang也支持面向对象编程(OOP),但是和传统的面向对象编程有区别,并不是纯粹的面向对象语言。所以我们说Golang支持面向对象编程特性是比较准确的。

2、Golang没有类(class),Go语言的结构体(struct)和其它编程语言的类(class)有同等的地位,可以理解Golang是基于struct来实现OOP特性的。

3、Golang面向对象编程非常简洁,去掉了传统OOP语言的继承、方法重载、构造函数和析构函数、隐藏的this指针等等

4、Golang仍然有面向对象编程的继承,封装和多态的特性,只是实现的方式和其它OOP语言不一样,比如继承:Golang没有extends关键字,继承是通过匿名字段来实现。

5、Golang面向对象(OOP)很优雅,OOP本身就是语言类型系统(typesystem)的一部分,通过接口(interface)关联,耦合性低,也非常灵活。在Golang中面向接口编程是非常重要的特性。

对上图的说明:

1、将一类事物的特性提取出来(比如猫类),形成一个新的数据类型,就是一个结构体。

2、通过这个结构体,我们可以创建多个变量(实例/对象)

3、事物可以猫类,也可以是Person,Fish或是某个工具类。。。

代码如下:

结构体和结构体变量(实例)的区别和联系

基本语法:

type结构体名称struct{field1typefield2type}举例:

typeCatstruct{NamestringAgeintColorstringHobbystring}字段/属性基本介绍

1、从概念或叫法上看:结构体字段=属性=field

2、字段是结构体的一个组成部分,一般是基本数据类型、数组,也可是引用类型。比如我们前面定义猫结构体的Namestring就是属性

4、不同结构体变量的字段是独立,互不影响,一个结构体变量字段的更改,不影响另外一个,结构体是值类型。

varpersonPersonfuncmain(){varpersonPersonperson.Name="bingle"person.Age=18fmt.Println("nameis",person.Name)fmt.Println("ageis",person.Age)}方式—2:{}

varpersonPerson=Person{}funcmain(){person:=Person{Name:"bingle",Age:18,}fmt.Println("nameis",person.Name)fmt.Println("ageis",person.Age)}方式—3:&varperson*Person=new(Person)funcmain(){varperson*Person=new(Person)//因为person是一个指针,因此标准的给字段赋值方式//(*person).Name="bingle"也可以这样写person.Name="bingle"//原因:go的设计者为了程序员使用方便,底层会对person.Name="bingle"进行处理//会给person加上取值运算(*person).Name="bingle"(*person).Name="bingle"person.Name="bingle"//(*person).Age=30person.Age=100fmt.Println(*person)fmt.Println("nameis",person.Name)fmt.Println("ageis",person.Age)}方式—4:{}

varperson*Person=&Person{}funcmain(){//下面的语句,也可以直接给字符赋值//varperson*Person=&Person{"bingle",60}varperson*Person=&Person{}//因为person是一个指针,因此标准的访问字段的方法//(*person).Name="bingle"//go的设计者为了程序员使用方便,也可以person.Name="bingle"//原因和上面一样,底层会对person.Name="bingle"进行处理,会加上(*person)(*person).Name="bingle"person.Name="bingle~~"(*person).Age=88person.Age=10fmt.Println("nameis",person.Name)fmt.Println("ageis",person.Age)}说明:

1、第3种和第4种方式返回的是结构体指针。

2、结构体指针访问字段的标准方式应该是:(*结构体指针).字段名,比如(*person).Name="bingle"

3、但go做了一个简化,也支持结构体指针.字段名,比如person.Name="bingle"。更加符合程序员使用的习惯,go编译器底层对person.Name做了转化(*person).Name。

我们来看一个思考题:

定义一个Person结构体

下面一段代码输出什么内容?

packagemainimport"fmt"typePersonstruct{NamestringAgeint}funcmain(){varperson1Personperson1.Age=18person1.Name="bingle1111"varperson2Person=person1fmt.Println(person2.Age)person2.Name="bingle2222"fmt.Printf("person2.Nameis%v,person1.Nameis%v",person2.Name,person1.Name)}输出结果:

变量总是存在内存中的,那么结构体变量在内存中是怎样存在的?

结构体在内存中的示意图:(和上面牛魔王、青牛精一个原理)

是值拷贝,内存空间是完全独立的

看下列代码,并分析原因:

funcmain(){varperson1Personperson1.Age=18person1.Name="bingle1111"varperson2*Person=&person1fmt.Println(*person2.Age)}不能这样写,会报错,原因是,.的运行优先级比*高

结构体使用注意事项和细节

1、结构体的所有字段在内存中是连续的

看下列代码:

packagemainimport"fmt"//结构体typePointstruct{xintyint}//结构体typeRectstruct{leftUp,rightDownPoint}funcmain(){r1:=Rect{Point{1,2},Point{3,4},}//r1有四个int,在内存中是连续分布//打印地址fmt.Printf("r1.leftUp.x地址=%pr1.leftUp.y地址=%pr1.rightDown.x地址=%pr1.rightDown.y地址=%p\n",&r1.leftUp.x,&r1.leftUp.y,&r1.rightDown.x,&r1.rightDown.y)}执行结果:

内存中的示意图:(int64是8个字节)

r2有两个*Point类型,这个两个*Point类型的本身地址也是连续的,但是他们指向的地址不一定是连续

2、结构体是用户单独定义的类型,和其它类型进行转换时需要有完全相同的字段(名字、个数和类型)

packagemainimport"fmt"typeAstruct{Numint}typeBstruct{Numint}funcmain(){varaAvarbBa=A(b)//可以转换,但是有要求,就是结构体的的字段要完全一样(包括:名字、个数和类型!)fmt.Println(a,b)}3、结构体进行type重新定义(相当于取别名),Golang认为是新的数据类型,但是相互间可以强转

packagemainimport"fmt"typeStudentstruct{NamestringAgeint}typeStuStudentfuncmain(){varstu1Studentvarstu2Stu//stu2=stu1//这样写是错误的,可以修改为stu2=Stu(stu1)stu2=Stu(stu1)fmt.Println(stu1,stu2)}4、struct的每个字段上,可以写上一个tag,该tag可以通过反射机制获取,常见的使用场景就是序列化和反序列化。

序列化的使用场景:

举例:

方法

对上面的总结

1、test方法和Person类型绑定

2、test方法只能通过Person类型的变量来调用,而不能直接调用,也不能使用其它类型变量来调用

3、func(thisPerson)test(){}...this表示哪个Person变量调用,这个this就是它的副本,这点和函数传参非常相似。

4、this这个名字,有程序员指定,不是固定,比如修改成person也是可以

方法快速入门

1、给Person结构体添加speak方法,输出xxx是一个好人

func(thisPerson)speak(){fmt.Println(this.Name,"是一个好人")}funcmain(){varpersonPersonperson.Name="bingle"person.speak()}2、给Person结构体添加jisuan方法,可以计算从1+..+1000的结果,说明方法体内可以函数一样,进行各种运算

func(thisPerson)jisuan(){res:=0fori:=1;i<=1000;i++{res+=i}fmt.Println(this.Name,"计算的结果是=",res)}3、给Person结构体jisuan2方法,该方法可以接收一个数n,计算从1+..+n的结果

func(thisPerson)jisuan2(nint){res:=0fori:=1;i<=n;i++{res+=i}fmt.Println(this.Name,"计算的结果是=",res)}5、方法的调用

funcmain(){varpersonPersonperson.Name="bingle"person.test()person.speak()person.jisuan()person.jisuan2(10)}方法的调用和传参机制原理方法的调用和传参机制和函数基本一样,不一样的地方是方法调用时,会将调用方法的变量,当做实参也传递给方法。下面,给Person结构体添加getSum(n1,n2)方法,计算两数的和,并返回结果:func(thisPerson)getSum(n1,n2int)int{returnn1+n2}funcmain(){varpersonPersonperson.Name="bingle"n1:=10n2:=20res:=person.getSum(n1,n2)fmt.Println("res=",res)}终端结果:

说明:

1、在通过一个变量去调用方法时,其调用机制和函数一样

2、不一样的地方时,变量调用方法时,该变量本身也会作为一个参数传递到方法(如果变量是值类型,则进行值拷贝,如果变量是引用类型,则进行地质拷贝)

func(receviertype)methodName(参数列表)(返回值列表){方法体return返回值}1、参数列表:表示方法输入

2、receviertype:表示这个方法和type这个类型进行绑定,或者说该方法作用于type类型

3、receivertype:type可以是结构体,也可以其它的自定义类型

4、receiver:就是type类型的一个变量(实例),比如:Person结构体的一个变量(实例)

5、返回值列表:表示返回的值,可以多个

6、方法主体:表示为了实现某一功能代码块

修改成如下:

3、Golang中的方法作用在指定的数据类型上的(即:和指定的数据类型绑定),因此自定义类型,都可以有方法,而不仅仅是struct,比如int,float32等都可以有方法(有点类似于C#中的扩展方法)

创建结构体变量时指定字段值

typeStustruct{NamestringAgeint}方式1:funcmain(){//方式1//在创建结构体变量时,就直接指定字段的值varstu1=Stu{"bingle1111",18}//stu1--->结构体数据空间stu2:=Stu{"bingle2222~",18}//在创建结构体变量时,把字段名和字段值写在一起,这种写法,就不依赖字段的定义顺序.varstu3=Stu{Name:"bingle3333",Age:18,}stu4:=Stu{Age:18,Name:"bingle4444",}fmt.Println(stu1,stu2,stu3,stu4)}

THE END
1.丘疹性荨麻疹起初症状生活中也需要注意的细节丘疹性荨麻疹我们在给与治疗的同时,还需要一定要注意是我们的生活环境的一些影响因素,首先在平时的时候要经常晒被子,屋内屋外喷洒杀虫剂,尽量的不养猫狗等宠物,减少病虫的产生!开封市儿童医院皮肤科李建设 家长们需要注意的是要防止因瘙痒引起的搔抓,防止继发脓疱疮。因此,发生这种疾病时,我们一定要带孩子到医院及时治疗。如果在...https://tag.120ask.com/jibing/qzxmz/810970.html
2.你这不是养猫,是请了个祖宗?20款国产猫粮分析与推荐,踩雷必看...穷养猫和富养猫完全在于个人愿意投资到宠物身上的水平,只要你不弃养不虐待,在自己的能力范围之内选择猫食物是完全没有问题的。 养宠物之前要考虑清楚,既然带回了这个小生命,就要为它将来15-18年的猫生负责。 科学喂养的意义在于能提供全面的营养配方,能让猫咪更健康、更长寿,只要自己带着脑子,耐心做一些功课,拒绝...https://www.miaomiaozhe.com/post/243526
1.新手养蓝猫必知的7个注意事项作为一个新手铲屎官,养蓝猫可不是一...新手养蓝猫必知的7个注意事项 作为一个新手铲屎官,养蓝猫可不是一件容易的事。以下是一些你需要特别注意的地方,否则你的猫咪可能会变成一个小恶魔哦~ 不要直接用手指逗小猫 小猫会误以为你的手是玩具,从而对你的手又抓又咬。玩耍时一定要用逗猫棒。 犯错要及时纠正 小猫破坏家里的东西时,一定要及...https://www.yoojia.com/article/4174215086007759744.html
2.《C语言入门指南》合集版,学习c语言有这一篇就够了?!xx.c!注意: 1、在c中,没有字符串类型,是使用字符串数组来表示字符串 2、在不同系统上,部分数据类型的字节长度不一样:例如int ,字节数可能为2,也可能为4 整数类型 下表列出了关于标准整数类型的存储大小和值范围的细节: 解释:signed int 就是不区分正负的类型 精度> int的精度 ...https://blog.csdn.net/weixin_44420143/article/details/109452756
3.大数据技术之16Scala学习04函数式编程举例5.10.5 Scala 异常处理小结5.11 函数的练习题第六章 面向对象编程-基础6.1 类与对象6.1.1 Scala 语言是面向对象的6.1.2 快速入门-面向对象的方式解决养猫问题6.1.3 类和对象的区别和联系...https://blog.51cto.com/u_15065849/4560154
4.女孩养猫10天变“秃头”?养宠物这些小细节不注意,传染病找上门...这些传染病要注意 五一假期期间,女孩从宠物店抱回了一只猫咪回家养,结果猫养了不到十天,女孩脑门一处开始掉头发,去医院检查头皮,发现感染了真菌头癣,治疗脑门上方这个感染部位需要剃光头发才能涂药。 据了解,女孩感染的是猫癣,是猫感染的一种皮肤病。猫咪单纯感染猫癣后一般不会瘙痒(少数对真菌过敏的猫咪会产生瘙痒...https://static.nfapp.southcn.com/content/202105/13/c5254489.html
5.七年级上册语文《猫》教案(通用10篇)第三次养猫感情波动幅度更大。先是“不大喜欢它”,听说芙蓉鸟被咬死后,“我”“很愤怒”。打了它之后“我心里还愤愤地,以为惩戒得还没有快意”。直到发现另一只黑猫衔着第二只黄鸟,“我开始觉得我是错了!”“我心里十分地难过”“难过得多”。文章的主题,正是通过对“我”一系列复杂感情变化的细节描写来不...https://www.fwsir.com/jiaoan/html/jiaoan_20220210160008_1634058.html
6.《猫》优秀教学设计(通用10篇)作为一名无私奉献的老师,通常需要用到教学设计来辅助教学,借助教学设计可以更大幅度地提高学生各方面的能力,从而使学生获得良好的发展。那么教学设计应该怎么写才合适呢?以下是小编整理的《猫》优秀教学设计,希望对大家有所帮助。 《猫》优秀教学设计 篇1 【教材https://mip.ruiwen.com/jiaoxuesheji/3508915.html
7.社区卫生知识讲座(通用14篇)对于过敏体质的小朋友来讲,因为自然界中的过敏源有很多很多:如花粉、虫蠕、动物羽毛、冷的空气,所以要特别注意:如对花粉过敏的,在花粉播散期要减少户外活动,特别是公园里,鲜花房,家里不养猫、狗等小动物,不用地毯,外出戴口罩等。 七、水痘 水痘是一种常见的传染病,好发于14岁以下的儿童,水痘主要 ...https://www.360wenmi.com/f/file5f9y3q24.html
8.实验细节的改进11篇(全文)二、实验仪器构造细节 根据实验目的和实验条件选择适合的仪器, 需要清楚仪器的构造。仪器的构造决定着仪器使用时的注意点, 而明晰仪器的构造莫过于进入实验室进行真实的触摸或操作体验, 以避免“纸上识记实验”使实验仪器变得抽象。 题2以下实验操作正确的是___。 ①可用...https://www.99xueshu.com/w/ikeywolinzif.html
9.治支气管炎有什么偏方支气管炎要注意这些细节支气管炎注意事项二: 患者居住房间应经常打开窗户,保持空气流通和干燥。房屋内的陈设应尽可能简单,以减少灰尘堆积,消除螨虫的滋生地。赶紧在室内铺设地毯,并用吸尘器和湿布清洁房间,防止灰尘飞扬。不要在室内吸烟,不要养猫、狗、鸟等动物,不要养花,因为有些花粉会引起过敏,诱发支气管炎。 https://xkyczp.com/detail/187240.html
10.养电子宠物能一夜暴富?妈妈养猪,女儿养猫,统统暴雷!一想到这些,孤独的情绪像潮水般涌来。刘梦雅快速拿出手机摆弄,想转移注意力。她点开了一款叫“喵喵”的App,这是一款养猫APP。 刘梦雅手机养猫有一段时间了。合租室友不同意她养猫,她只能靠养猫游戏来体验养猫的乐趣。机缘巧合,在游戏论坛里结识的朋友赵云介绍了这款“喵喵”App。不仅可以养猫,还能赚钱,而且回报...https://news.hexun.com/2020-09-07/202023453.html