Golang简易入门教程——面向对象篇
本文始发于个人公众号:TechFlow,原创不易,求个关注
今天是golang专题的第9篇文章,我们一起来看看golang当中的面向对象的部分。
在现在高级语言当中,面向对象几乎是不可或缺也是一门语言最重要的部分之一。golang作为一门刚刚诞生十年的新兴语言自然是支持面向对象的,但是golang当中面向对象的概念和特性与我们之前熟悉的大部分语言都不尽相同。比如Java、Python等,相比之下, golang这个部分的设计非常得简洁和优雅(仁者见仁),所以即使你之前没有系统地了解过面向对象,也没有关系,也一定能够看懂。
常见的面向对象的部分,比如继承、构造函数、析构函数,这些内容在golang当中统统没有,因此整体的学习成本和其他的语言比起来会更低一些。
struct
在golang当中没有类的概念,代替的是结构体(struct)这个概念。我们可以给结构体类型定义方法,为了表明该方法的适用对象是当前结构体,我们需要在方法当中定义接收者,位于func关键字和方法名之间。
我们一起来看一个例子:
type Point struct {
x int
y int
}
func (p Point) Dis() float64 {
return math.Sqrt(float64(p.x*p.x + p.y*p.y))
}
在上面这段代码当中我们定义了一个叫做Point的结构体,以及一个面向这个结构体的方法Dis。我们一个一个来看它们的语法。
对于结构体来说,我们通过type关键字定义。在golang当中type关键字的含义是定义一个新的类型。比如我们也可以这样使用type:
type Integer int
它的含义是从int类型定义了一个新的类型Integer,从此之后我们可以在后序的代码当中使用Integer来代替int。它有些类似于C++当中的typedef,结合这个含义,我们再来看结构体的定义就很好理解了。其实是我们通过struct关键字构造了一个结构体,然后使用type关键字定义成了一个类型。
之后我们创建了一个面向结构体Point的函数Dis,这个函数和我们之前使用的函数看起来并没有太多的不同,唯一的区别在于我们在func和函数名之间多了一个(p Point)的定义。这其实是定义这个函数的接收者,也就是说它接受一个结构体的调用。
不仅如此,我们可以给golang当中的任何类型添加方法,比如:
type Integer int
func (a Integer) Less(b Integer) bool {
return a < b
}
在这个例子当中,我们给原生的int类型添加了Less这个方法,用来比较大小。我们在添加方法之前使用type给int起了一个别名,这是因为golang不允许给简单的内置类型添加方法,并且接收者的类型定义和方法声明必须在同一个包里,我们必须要使用type关键字临时定义一个新的类型。这里要注意的是,虽然我们定义出来的Integer和int的功能完全一样,但是它们属于不同的类型,不能互相赋值。
和别的语言比较起来,这样的定义的一个好处就是清晰。举个例子,比如在Java当中,同样的功能会写成不同的样子:
class Integer {
private int val;
public boolean less(Integer b) {
return this.val < b.val;
}
}
对于初学者而言,可能会觉得困惑,less函数当中的这个this究竟是哪里来的?其实这是因为Java的成员方法当中隐藏了this这个参数,这一点在Python当中要稍稍清晰一些,因为它将self参数明确地写了出来:
class Integer:
def __init__(self, val):
self.val = val
def less(self, val):
return self.val < val.val
而golang明确了结构体函数的接收者以及参数,显得更加清晰。
指针接收者
golang当中,我们也可以将函数的接收者定义成指针类型。
比如我们可以将刚才的函数写成这样:
type Point struct {
x int
y int
}
func (p *Point) Dis() float64 {
return math.Sqrt(float64(p.x*p.x + p.y*p.y))
}
指针接收者和类型接收者在使用上是一样的,我们并不需要将结构体转化成指针类型,可以直接进行调用。golang内部会自己完成这个转化:
func main() {
p := Point{3, 4}
fmt.Print(p.Dis())
}
那么这两者的区别是什么呢?我们既然可以定义成普通的结构体对象,为什么还要有一个指针对象的接收者呢?
其实很好理解, 两者的区别有些类似于C++当中的值传递和引用传递。在值传递当中,我们传递的是值的一个拷贝,我们在函数当中修改参数并不会影响函数外的结果。而引用传递则不然,传递的是参数的引用,我们在函数内部修改它的话,会影响函数外的值。
也就是说在golang当中,如果我们函数接收的是一个指针类型,我们可以在函数内部修改这个结构体的值。否则的话,传入的是一个拷贝,我们在其中修改值并不会影响它本身。我们来看个例子:
func (p *Point) Modify() {
p.x += 5
p.y -= 3
}
func main() {
p := Point{3, 4}
p.Modify()
fmt.Print(p)
}
上面这段代码当中函数的接收者是一个指针,所以我们得到的结果会是{8, 1},如果我们把指针去掉,改成普通的值接收的话,那么最后的结果仍然是{3, 4}。
总结
我们今天学的内容有些多,我们来简单梳理一下。首先,我们了解了通过type和struct关键字来定义一个结构体,结构体是golang当中面向对象的载体,golang抛弃了传统的面向对象的实现方式和特性,拥有自己的面向对象的理念。
对于结构体来说,我们可以把它当做是接受者传递给一个函数,使得我们可以以类似调用类当中方法的形式来调用一个函数。并且对于函数而言,接受者除了值以外还可以是一个指针。如果是指针的话,当我们对结构体值进行修改的时候,会影响到原值。即使我们定义的接收者类型是指针,我们在调用的时候也不必显示将它转化成结构体指针,golang当中会自动替我们完成这样的转化。
面向对象部分可以说是golang这一门语言当中最大的创新之一,也正是因为抛弃了传统的类以及继承、派生的概念,使得golang当中的面向对象语法糖相对简洁。也因此有人将golang称为升级版的C语言。虽然我们啰啰嗦嗦写了很多,但是实际谈到的内容并不多,我想理解起来也不会特别困难。
今天的文章到这里就结束了,如果喜欢本文,可以的话,请点个关注,给我一点鼓励,也方便获取更多文章。
本文使用 mdnice 排版
Golang简易入门教程——面向对象篇的更多相关文章
- Web压力测试工具 LoadRunner12.x简易入门教程--(一)回放与录制
LoadRunner12.x简易入门教程--(一)回放与录制 今天在这里分享一下LoadRunner12.x版本的入门使用方法,希望对刚接触LoadRunner的童鞋有所帮助. LoadRun ...
- Golang简单入门教程——函数进阶篇
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是golang专题的第八篇,我们来聊聊golang当中的函数. 我们在之前的时候已经介绍过了函数的基本用法,知道了怎么样设计或者是定义一 ...
- Pytest自动化测试-简易入门教程(02)
Pytest框架简介 Pytest是一个非常成熟的全功能的Python测试框架,主要有以下几个特点:1.简单灵活,容易上手,支持参数化2.能够支持简单的单元测试和复杂的功能测试,3.还可以用来做sel ...
- Lua简易入门教程
环境:lua for windows (lfW)主页:http://luaforwindows.luaforge.net/https://code.google.com/p/luaforwindows ...
- 最新hadoop入门教程汇总篇(附详细图文步骤)
关于hadoop的分享此前一直都是零零散散的想到什么就写什么,整体写的比较乱吧.最近可能还算好的吧,毕竟花了两周的时间详细的写完的了hadoop从规划到环境安装配置等全部内容.写过程不是很难,最烦的可 ...
- Webpack简易入门教程
<!-- 其实网上关于webpack的教程已经很多了,但是本人在学习过程中发现很多教程有错误,或者写的很不全面,结果做的过程出现各种各样的问题,对新手不但不友好还会让人浪费很多不必要的时间.所以 ...
- Pytest自动化测试-简易入门教程(01)
我们今天主讲的内容,就是测试框架Pytest,讲到这个测试框架对于没有做过Web自动化的伙伴来说,会觉得这个东西是陌生的,那么到底什么是框架呢?什么又是自动化呢?自动化为什么又要用框架呢? 难道我学自 ...
- IOS开发入门教程-总结篇-写给狂热的编程爱好者们
程序发轻狂,代码阑珊,苹果开发安卓狂!--写给狂热的编程爱好者们 写在前面的话 学习iOS应用程序开发已有一段时间,最近稍微闲下来了,正好也想记录一下前阶段的整个学习过程.索性就从最基础的开始,一步一 ...
- 给萌新的Flexbox简易入门教程
转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 原文出处:https://www.sitepoint.com/flexbox-css-flexible-bo ...
随机推荐
- 【书签】连续型特征的归一化和离散特征的one-hot编码
1. 连续型特征的常用的归一化方法.离散型特征one-hot编码的意义 2. 度量特征之间的相关性:余弦相似度和皮尔逊相关系数
- echo改变字体颜色
格式: echo -e "\033[字背景颜色;字体颜色m字符串\033[0m" 例如: echo -e "\033[41;36m something here \033 ...
- 一文带你深入理解JVM,看完之后你还敢说你懂JVM吗?颠覆you认知
前言 今天带大家深入理解JVM,从入门到精通,希望大家能够喜欢~~~ 概念 JVM是可运行 Java 代码的假想计算机 ,包括一套字节码指令集.一组寄存器.一个栈.一个垃圾回收,堆 和 一个存储方法域 ...
- Beta冲刺 —— 总结随笔
这个作业属于哪个课程 软件工程 这个作业要求在哪里 Beta冲刺 这个作业的目标 Beta冲刺 作业正文 正文 github链接 项目地址 其他参考文献 无 一.项目预期计划: 1.对于初版小程序的现 ...
- css 段落文字换行问题
项目中遇到的一个小问题,以前没有注意到: 超链接超出父级元素,想着给a标签加宽度但是没有效果... 后来发现两个很好用的css属性 1.word-wrap 用来控制换行 取值: (1)normal ...
- Java实现 蓝桥杯VIP 基础练习 字符串对比
问题描述 给定两个仅由大写字母或小写字母组成的字符串(长度介于1到10之间),它们之间的关系是以下4中情况之一: 1:两个字符串长度不等.比如 Beijing 和 Hebei 2:两个字符串不仅长度相 ...
- Java GUI 鼠标事件
import java.awt.Button; import java.awt.FlowLayout; import java.awt.Frame; import java.awt.event.Mou ...
- 一张图说清楚Flink水印和Lateness
真传一句话,假言万卷书. Flink使用窗口与水印处理乱序问题,使用Latenss处理延迟问题,二者混合使用可以满足很多复杂场景的需求 当Watermark大于窗口结束时间时,会触发窗口内的元素进行计 ...
- 遇到Error:Execution failed for task ':app:transformClassesWithDexForDebug'的解决方案
原因:项目中包含了所有的google play service 解决:只需要使用必要的服务即可 将compile 'com.google.android.gms:play-services:8.1.0 ...
- Ubuntu一键安装Mariadb
系统版本: debian/ ubuntu/ 添加清华大学镜像库: sudo add-apt-repository -r 'https://mirrors.tuna.tsinghua.edu.cn/m ...