跟着老猫来搞GO,"面向对象"
前言
之前和大家分享了容器以及相关的基础语法,以及函数,相信如果大家有接触过C++或者java的朋友都晓得面向对象,其实在GO语言中也存在面向对象,但是还是比较简单的,下面我们来看一下GO语言的“面向对象”。
面向对象
结构体的定义
其实在GO语言中并不能准确得说是面向对象,go语言其实是面向接口函数编程的语言。为什么要说成GO语言的面向对象,其实也是部分特性类似于面向对象。GO语言中的面向对象还是比较简单的,GO语言仅支持封装,不支持多态和继承。语言没有class,只有struct。
结构体本质上也是一种数据类型,它是将0个或者多个任意类型的命名变量组合在一起的聚合数据类型,其中每个变量都叫做结构体的成员。看下结构体的定义,具体如下
type Employee struct {
ID int //id编号
Name string //名称
Address string //地址
Position string //职位
}
func main() {
var jack Employee
jack.Name = "jack"
jack.Address = "shanghai"
fmt.Println(jack.Name)
}
以上我们就定义一个员工的结构体,这个结构体包含了名称、地址、职位等一些属性。在main函数中,我们创建了一个Employee类型的jack,并且给予其初始化了值。上述比较简单地,咱们可以直接用“.”的方式进行对结构体变量进行赋值以及取值,当然咱们也可以获取成员变量的地址,然后通过指针来访问它。如下:
func main() {
var jack Employee
jack.Name = "jack"
jack.Address = "shanghai"
jack.Position = "Engineer"
//fmt.Println(jack.Name)
position := &jack.Position
*position = "Senior" + *position
fmt.Println(*position)
}
显然这里的jack被升值了,变成了高级工程师。
咱们的点号其实也可以直接用在结构体的指针上,如下
func main() {
var jack Employee
jack.Name = "jack"
jack.Address = "shanghai"
jack.Position = "Engineer"
//fmt.Println(jack.Name)
position := &jack.Position
*position = "Senior" + *position
//fmt.Println(*position)
var employeeA *Employee = &jack
employeeA.Position = "Super" + employeeA.Position
fmt.Println(employeeA.Position)
}
还没理解透彻指针的小伙伴可以会有点懵,后面老猫还是专门把指针说一下。上面的那个步骤,我们只是获取了jack的职位并通过指针将其重新赋值升级,那么下面,其实咱们就定义了一个Employee的指针,并且这个指针指向的是jack这个结构体,那么针对我们的employeeA这个员工指针就能获取其结构体中所有的属性,并且将其重新赋值。
当然我们甚至可以定义指针类型的结构体函数,当然,其返回值必须是某个结构体的地址,具体定义如下:
func EmployeeByID(id int) *Employee {
var json Employee
json.ID = id
json.Name = "json"
json.Address = "beijing"
json.Position = "Engineer"
return &json
}
上述,咱们主要介绍了结构体以及指针的相关的用法,那么关于结构体的话还有哪些注意点呢?
- 成员变量的顺序对于结构体同一性很重要,如果我们将上面的Employee结构体的属性进行顺序颠倒调换,那么我们就说定义了另外一个不同类型的结构体。
- 关于GO结构中定义变量的大小写,大家可以看到,老猫上述定义的都是以大写字母开头的,因为只有以大写字母开头定义的属性,才能够被外围访问。大家可以手动敲一下代码体验一下。这个也是GO最主要的访问控制机制。
- 结构体类型不可以定义一个拥有相同结构体类型s的成员变量,也就是一个聚合类型不可以包含它自己。
这个是什么意思呢?咱们来看一下例子!

上图我们可以看到,如果结构体中套有自身是会报编译错误的。但是Employee中可以定义个S的指针类型。例如下面则是OK的
type Employee struct {
ID int
Name string
Address string
Position *Employee
}
所以咱们就可以利用这种形式来做递归结构的定义,例如链表或者树的定义咱们就可以这么来定义
type tree struct {
value int
left,right *tree
}
结构体的字面量
这里说的字面量就是结构体中的值,我们结构体类型中的值可以通过结构体字面量来进行设置。如下,有两种结构体字面量。
第一种
type Point struct {X,Y int}
p:=Point{1,2}
这种方式要求按照正常顺序为每个成员变量进行赋值,很显然,如果结构体比较简单的时候无所谓,但是一旦结构体之后随着业务的演化变得相当复杂的时候,代码的可维护性就变得相当差了。
第二种
type Point struct {X,Y int}
p:=Point{X:1,Y:2}
这种方式显然会比较清晰一些,但是需要注意的是如果其中某个成员变量没有指定的值的话,那么其值默认就为零值。由于指定了成员变量的名字,在这种方式中相当于第一种而言,这里的顺序就无所谓了。
结构体的比较
如果结构体的所有成员变量都可以比较,那么这个结构体就是可以比较的,两个结构体的比较直接使用==或者!=即可。
p:=Point{1,2}
q:=Point{2,1}
e:=Point{1,2}
fmt.Println(q.x == p.x) //成员函数比较 false
fmt.Println(p == q) //整体比较 false
fmt.Println(p == e) // true
在面向对象语言中,例如java,在我们比较两个对象值的时候需要去比较两个对象的hash值,甚至需要重写equals方法,我们在这里看到的go语言的结构体对象的比较就很简单明了了。这里不多赘述,还是希望大家能够多写写。
结构体的嵌套机制
结构体的嵌套机制可以让我们将一个命名结构体当做另一个结构体类型的匿名成员来使用。这句话可能有点不好理解,我们还是来直接看一下例子。
首先咱们来定义一个圆,圆的话包含了圆心的坐标以及相关的半径,由此,咱们可以抽象出如下代码
type Circle struct {
X,Y,Radius int
}
在我们的日常生活中,轮子也是圆形的,轮子可能多一些条幅数,由此,咱们轮子也可以抽象一下
type Wheel struct {
X,Y,Radius,Spokes int
}
看到上述两个,咱们其实可以发现这两个结构体中有挺多相同的成员变量,那咱们是不是可以再度抽象一下,于是咱们就抽象成了如下:
type Circle struct {
Center Point
Radius int
}
type Wheel struct {
Circle Circle
Spokes int
}
这样,咱们就会发现整个程序看起来变得更加清晰。其实这也是更好地说明了结构体说白了也是一种特殊的数据类型而已。
写在最后
本篇中其实和大家粗略分享了结构体的相关知识,有java相关面向对象语言经验的小伙伴会发现,结构体和面向对象语言中的类比较相像,但是GO语言中的结构体的用法相比之下会简单得多。
我是老猫,更多内容,欢迎大家搜索关注老猫的公众号“程序员老猫”。

跟着老猫来搞GO,"面向对象"的更多相关文章
- 跟着老猫来搞GO,集跬步而致千里
上次博客中,老猫已经和大家同步了如何搭建相关的GO语言的开发环境,相信在车上的小伙伴应该都已经搞定了环境了.那么本篇开始,我们就来熟悉GO语言的基础语法.本篇搞定之后,其实期待大家可以和老猫一样,能够 ...
- 跟着老猫来搞GO-容器(1)
前期回顾 前面的一章主要和大家分享了GO语言的函数的定义,以及GO语言中的指针的简单用法,那么本章,老猫就和大家一起来学习一下GO语言中的容器. 数组 数组的定义 说到容器,大家有编程经验的肯定第一个 ...
- 跟着老猫来搞GO,基础进阶
回顾一下上一篇博客,主要是和大家分享了GO语言的基础语法,其中包含变量定义,基本类型,条件语句,循环语句.那本篇呢就开始和大家同步一下GO语言基础的进阶. 函数的定义 上次其实在很多的DEMO中已经写 ...
- 跟着老猫来搞GO-内建容器Map
前期回顾 在上面的文章中,老猫和大家分享了GO语言中比较重要的两种数据结构,一种是数组,另外一种是基于数组的slice.本篇文章想要继续和大家分享剩下的容器以及字符字符串的处理. MAP map的定义 ...
- 跟着老猫一起来学GO,环境搭建
老猫的GO学习系列博客已经正式发车了,相信大家以前学习一门编程语言的时候也有经验,咱们一般都是从环境开始,在此呢,大家也跟着老猫从最开始的搭建环境开始. GO语言的安装 首先呢,我们开始需要下载GO语 ...
- 我用Axure制作了一款火影小游戏 | PM老猫
Axure不仅仅是一个原型工具,除了原型之外还可以用来制作一些静态网页,这点对于不懂代码或前端的同学来说挺实用.之前整理了一版<Axure函数自查表>,因为感觉内容太多又对前端样式及脚本感 ...
- 跟着老王学Python
亲爱的朋友: 欢迎你!很高兴能在这里见到你,你能来到这里说明你真的很喜欢python,很想把python给学好!我觉的你很幸运,开始我学python的时候比较少资料,学起来也比较头疼,现在随着 ...
- 【vue】跟着老马学习vue-数据双向绑定
学习了node.js教程,只能说是有了一定的了解,之前也了解了webpack和es6的核心内容,也看过vue2.0的官网教程,并结合视频看过项目,但是理解和运用仍然存在很多问题,接下来的一段时间,跟着 ...
- 跟着刚哥梳理java知识点——面向对象(八)
面向对象的核心概念:类和对象. 类:对一类事物描述,是抽象的.概念上的定义. 对象:实际存在的该类事物的每个个体,因而也成为实例(Instance). Java类及类的成员:属性(成员变量Field) ...
随机推荐
- 重庆邮电大学第十一届ACM程序设计竞赛-网络选拔赛 C题
1008: 偷袭 时间限制: 1.000 sec 内存限制: 128 MB 武林要以和为贵,张麻子不讲武德来偷袭马老师的亲传弟子. 马老师有n个亲传弟子,每个弟子有一个武力值a[i]. n个弟子中只有 ...
- springboot事务的传播行为和隔离级别
springboot事务的传播行为和隔离级别 在springboot中事务的传播行为和隔离级别都是在TransactionDefinition这个接口中定义的 传播行为定义了7种,分别用0-6来表示 ...
- 【Spring】IoC容器 - 依赖查找
前言 上一篇文章已经学习了[IoC的主要实现策略]有2种: 1.依赖查找 2.依赖注入 这里稍加详细的介绍一下依赖查找 1.依赖查找的方式 依赖查找的方式可以以多种维度来划分: 1.按名称/类型/注解 ...
- 第三次Scrum Metting
日期:2021年4月27日会议主要内容概述:确定后端和前端接口,前端讨论画图页面,解决两处画图问题 一.进度情况# 组员 负责 两日内已完成的工作 后两日计划完成的工作 工作中遇到的困难 徐宇龙 后端 ...
- [对对子队]会议记录4.18(Scrum Meeting9)
今天已完成的工作 何瑞 工作内容:修复了一些关卡1的bug 相关issue:搭建关卡1 相关签入:4.18签入1 4.18签入2 梁河览 工作内容:实现了音量控制,添加了BGM 相 ...
- 生产环境部署springcloud微服务启动慢的问题排查
今天带来一个真实案例,虽然不是什么故障,但是希望对大家有所帮助. 一.问题现象: 生产环境部署springcloud应用,服务部署之后,有时候需要10几分钟才能启动成功,在开发测试环境则没有这个问题. ...
- android tcp通讯
Andoird TCP通讯 前言 最近在写一个即时通讯的项目,有一些心得,写出来给大家分享指正一下. 简单描述一下这个项目: 实时查询车辆运行状态的项目,走TCP通迅. 接口采用GZIP压缩. 后台是 ...
- 设计模式 - Bridge 桥模式
Bridge桥模式也属于"的单一职责"模式中的典型模式.问题描述:我们绘制图形时,图形可以有不同形状以及不同颜色,比如圆形可以是红的,绿的,方形可以是红的绿的,如果用代码来描绘这些 ...
- SkyWalking配上告警更优秀
前言 对于监控系统来说,不可能让人一直盯着监控看板,而更多的是以自动提醒的方式,比如邮件.短信或微信推送等,当达到或超出预设的告警指标时,就自动发送消息提醒,下面就来说说如何配置SkyWalking的 ...
- 最后的OI(HAOI2020游记)
马上就省选了,怎么不得写点什么?要不然到最后或许就真的落得个白茫茫大地真干净的局面. 其实也不知道该说啥?我这一路走来,感觉挺赚的. 每一个OIer背后都有一个故事,所以,我有故事,你有酒吗? 依稀记 ...