首页 > 其他分享 >go基础-方法

go基础-方法

时间:2023-08-03 18:11:52浏览次数:25  
标签:p1 Name 基础 Person go 方法 sayHi 函数

概述

方法是面向对象编程 (OOP) 的一个特性,在 C++/Java 语言中方法是类函数,go做为函数式编程语言,通过特有技能支持相似的功能,所以说go也支持面向对象编程特性。

go 方法本质也是函数,相比普通函数稍有区别,方法必须与具体类型绑定,且无法独立运行,只能通过类型实例执行,函数是一等公民,方法是二等公民。方法很像面向对象的类方法,但又有区别,方法更加松散,耦合性更低。类方法是定义在对象内部,go方法更像是一种属性扩展,在不修改类型定义的情况下可扩展方法,比如可为外部引入的结构体增加方法,这在Java、C#等面向对象语言是不允许的。

 

基本使用

方法可以绑定到任意类型,但是实际情况总是与结构体绑定,两者结合可以模拟面向对象特性,当然仅是模拟,文章主要使用结构体演示。

 

定义类型

type Person struct {
    Age   int
    Name  string
}

  

为结构体定义方法

func (p *Person) sayHi() {        // 为结构体定义了一个方法
    fmt.Println("hi, I'm ", p.Name)
}

相比普通函数定义稍有区别,在func关键字和函数名之间增加一个接收器,或称为接收者、连接器等,如上接收器是Person类型指针。与接收器参数匹配的类型,就增加了一个新方法,目前观察这是go的独创。

 

方法方必须依实例,无法独立执行。与面型对象中方法一样,先有对象,才能调用方法。

sayHi() // error undefined: sayHi

 

必须通过结构体实例调用,会自动把实例传递给方法的接收器,类似JavathisPythonself,隐式传递第一个参数。

p1 := Person{Name: "tom"}
p1.sayHi()    // hi, I'm  tom

 

为简单理解,编译后伪代码如下

func sayHi(self) {        // self是体结构体指针
    fmt.Println("hi, I'm ", self.Name)
}

 

接收器参数类型,除非有明确需求,否则都应该使用指针。同样的问题,使用值类型本质是每次调用,都传入复制的新实例。

func (p Person) sayHi() {
    p.name = "tony"
    fmt.Println("hi, I'm ", p.Name)     // tony
}

func main() {
    p1 := Person{Name: "tom"}
    p1.sayHi()                        // 复制新结构体传递给sayHi
    fmt.Println(p1.Name)              // tom
}

  

语法层面没有限制,允许为任何类型创建方法,包括基础数据类型。但是有一个限制,方法和类型定义必须在同一个包,为基础数据类型、或引入第三方类型定义方法需要一些变通,先使用type定义类型,在扩展方法。

为基本数据类型扩展方法

type Integer int

func (m *Integer) Value() {
    fmt.Println(*m)
}

使用方法

var m Integer = 10
m.Value()    // 10

  

假如Person是从第三方引入的类型,为其扩展新方法

type MyPerson Person

func (m *MyPerson) getName() {
    return Person(*m).Name        // 先强制转为Person类型,再读取Name属性
}

使用方法

p1 := MyPerson{Name: "tom"}
p1.getName()

p1.sayHi    // err

sayHi是Person结构体的方法,无法通过MyPerson类型访问,也不支持常规的继承

 

更优雅是使用组合的方式(继承模式),Go 语言不支持传统面向对象中的继承特性,而是以自己特有的组合方式支持了方法的继承,通过在结构体内置匿名的成员来实现继承

type MyPerson struct {
    City string
    Person        // 匿名属性
}

func (m *MyPerson) getCity() {
    return m.City
}

 

使用方法

p1 := MyPerson{City: "shanghai"}
p1.getCity()    // shanghai

p1.sayHi()        // ok,调用继承方法

被继承的对象称为基础类型,属性、方法都可以被继承,注意继承方法在调用时连接器接收的对象是原始对象,如上案例中sayHi接收的是Person对象,而非MyPerson对象,这种展开是编译期完成的, 并没有运行时代价。这与C++、C#、Java主流面向对象语言不同,子类方法在运行时动态绑定到对象,因此基类某些方法看到的 this 可能不是基类类型对应的对象,这个特性会导致基类方法运行的不确定性。

 

方法是由函数演变而来,只是将函数第一个参数移动到函数名前面而已,方法是特殊的函数。两者特性几乎一样,比如都是值传递、都不支持重载,甚至通过方法表达式可以将方法还原为普通函数

sayHi := (*Person).sayHi            // 方法转换为函数

p := &Person{Age: 1, Name: "xk"}    // 创建结构体
sayHi(p)                            // 调用转换后的函数

转换为普通函数后,将接收器转换为函数的第一个参数,调用时候需要显示传递参数。

标签:p1,Name,基础,Person,go,方法,sayHi,函数
From: https://www.cnblogs.com/asdfzxv/p/17603570.html

相关文章

  • Django 模型(数据库)
    Django模型是与数据库相关的,与数据库相关的代码一般写在 models.py本节的代码:(Django1.6,Python2.7测试环境)learn_models.zip大家可以按照我的步骤来开始做:django-admin.pystartprojectlearn_models#新建一个项目cdlearn_models#......
  • 子组件调用父组件方法带参数
    子组件调用父组件方法带参数父组件###template<DBTableSelectref="DBTableEdit"@customEvent="handleCustomEvent"@close="closedDrawDBTable"v-if="showDrawDBTable"/>###jsimportDBTableS......
  • 自己整理的ASP.NET基础 (不断的更新)
    .列举ASP.NET页面之间传递值的几种方式。答.1).使用QueryString,如....?id=1;response.Redirect()....                 2).使用Session变量                 3).使用Server.Transfer--------------------------------------------......
  • js方法保持同步promiseAll
    单个请求保持同步-方法执行完再执行后面的语句delItem(item){if(item.row.status=='2'){this.$message.warning("需求在开发中,无法删除");return;}if(item.row.status=='3'){this.$message.warning("需求已开发完成,无法......
  • C++基础
    Talkischeap.Showmethecode.C++分为C++语言和C++标准库 版本演化可分为C++98(1.0),C++11(2.0),C++14话不多说,上代码头文件命名方式,例如complex.h首先要写防卫式声明,以前写的时候只是知道要写,现在知道才叫什么。1#ifndef_MYCOMPLEX_2#define_MYCOMPLEX_34......
  • 子组件调用父组件的方法
    父组件<importExcelref="importExcelEdit":disabled="ExcelDisabled"@closed="closedDrawExcel"v-if="showDrawExcel":labelItem="objectTypeKey"tabLabel="手动打标配......
  • Django之models模型层2
    一、多表查询之连表查询(基于双下划线的查询)1、2、3、  二、聚合查询(aggregate)1、2、   三、分组查询annotate 1、 2、  四、F与Q查询  五、django中如何开启事务 ......
  • go语言基础-关键字
    go代码中会使用到25个关键字和保留字breakdefaultfuncinterfaceselectcasedefergomapstructchanelsegotopackageswitchconstfallthroughifrangetypecontinueforimportreturnvargo代码经常用到的预定义标识符appendboolbytecapclo......
  • Excel中文本型数字转换为数值型数字的方法
    背景工作中经常遇到需要将Excel中的内容进行求和或者其他计算,但是由于格式为文本,无法进行计算和求和。单元格的左上角都有绿色小三角,且用自动求和公式计算无法计算结果,显示为0,说明单元格格式为文本。1、直接将文本转化成数字需要转换的数据,左上角会出现黄色感叹号,点击,并选择......
  • 2023 *CTF reverse gorev
    gorev用ida_7.7分析一直分析不出来,得用idafree_8.3分析。(是一道go语言逆向)分析流程就是读入input,然后异或 v22=encoding_base64__ptr_Encoding_EncodeToString看到这个以及后面图片的"="判断出是base64这个就是12345678901234567890123456789012经过异或再base64......