文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

go语言方法集为类型添加方法示例解析

2024-04-02 19:55

关注

1概述

在面向对象编程中,一个对象其实也就是一个简单的值或者一个变量,在这个对象中会包含一些函数,这种带有接收者的函数,我们称为方法(method)。本质上,一个方法则是一个和特殊类型关联的函数。

一个面向对象的程序会用方法来表达其属性和对应的操作,这样使用这个对象的用户就不需要直接去操作对象,而是借助方法来做这些事情。

在Go语言中,可以给任意自定义类型(包括内置类型,但不包括指针类型)添加相应的方法。

⽅法总是绑定对象实例,并隐式将实例作为第⼀实参 (receiver),方法的语法如下:

func (receiver ReceiverType) funcName (parameters) (results)

2为类型添加方法

2.1基础类型作为接收者

type MyInt int//自定义类型,给int改名为MyInt
//在函数定义时,在其名字之前放上一个变量,即是一个方法
func (a MyInt) Add(b MyInt) MyInt {//面向对象
    return a + b
}
//传统方式的定义
func Add(a, b MyInt) MyInt {//面向过程
    return a + b
}
func main() {
    var a MyInt=1   // a := MyInt(1)  等价
    var b MyInt=1
//调用func (aMyInt) Add(bMyInt)
fmt.Println("a.Add(b)=",a.Add(b))//a.Add(b)=2
//调用func Add(a,bMyInt)
fmt.Println("Add(a,b)=",Add(a,b))//Add(a,b)=2
}

通过上面的例子可以看出,面向对象只是换了一种语法形式来表达。方法是函数的语法糖,因为receiver其实就是方法所接收的第1个参数。

注意:虽然方法的名字一模一样,但是如果接收者不一样,那么方法就不一样。

2.2结构体作为接收者

方法里面可以访问接收者的字段,调用方法通过点(. )访问,就像struct里面访问字段一样:

package main
import "fmt"
func main(){
	jeff:=user{1,"jeff",18,"上海"}
	fmt.Println(jeff.Add(10))
}
// 相当于定义user类
type user struct {
	id int
	name string
	age int
	addr string
}
// 添加Add方法,接收参数num
func (p user) Add(num int)int{
	fmt.Println(p.age)
	return p.age+num
}

3值语义和引用语义

package main
import "fmt"
func main() {
	//指针作为接收者,引用语义
	jeff := Person{"jeff","男",18}//初始化
	fmt.Println("函数调用前=",jeff)//函数调用前= {jeff 男 18}
	(&jeff).Add()  // 生效,(&jeff)拿到jeff的地址(指针)
	//jeff.Add()  // 修改不生效
	fmt.Println("函数调用后=",jeff)//函数调用后= {aaa 女 22}
	fmt.Println("==========================")
	chary := Person{"chary","女",18}//初始化
	//值作为接收者,值语义
	fmt.Println("函数调用前=",chary)//函数调用前= {chary 女 18}
	chary.Add2()  //不生效
	//(&chary).Add()
	fmt.Println("函数调用后=",chary)//函数调用后= {chary 女 18}
}
type Person struct {
	name string
	sex string
	age int
}
//指针作为接收者,引用语义
func (p *Person) Add(){
	//给成员赋值
	(*p).name = "aaa"
	p.sex = "女"
	p.age = 22
}
//值作为接收者,值语义
func (p Person) Add2(){
	//给成员赋值
	p.name = "bbb"
	p.sex = "男"
	p.age = 22
}

4方法集

类型的方法集是指可以被该类型的值调用的所有方法的集合。

用实例实例 value 和 pointer 调用方法(含匿名字段)不受⽅法集约束,编译器编总是查找全部方法,并自动转换 receiver 实参。

4.1类型 *T 方法集

一个指向自定义类型的值的指针,它的方法集由该类型定义的所有方法组成,无论这些方法接受的是一个值还是一个指针。

如果在指针上调用一个接受值的方法,Go语言会聪明地将该指针解引用,并将指针所指的底层值作为方法的接收者。

类型 *T ⽅法集包含全部 receiver T + *T ⽅法:

type Person struct{
    name string
    sex byte
    age int
}
//指针作为接收者,引用语义
func (p *Person) SetInfoPointer(){
    (*p).name="yoyo"
    p.sex='f'
    p.age=22
}
//值作为接收者,值语义
func (p Person) SetInfoValue(){
    p.name="xxx"
    p.sex='m'
    p.age=33
}
func main() {
    //p为指针类型
    var p*Person = &Person{"mike",'m',18}
    p.SetInfoPointer()    //func (p)SetInfoPointer()
    p.SetInfoValue()    //func (*p)SetInfoValue()
    (*p).SetInfoValue()    //func (*p)SetInfoValue()
}

4.2类型 T 方法集

一个自定义类型值的方法集则由为该类型定义的接收者类型为值类型的方法组成,但是不包含那些接收者类型为指针的方法。

但这种限制通常并不像这里所说的那样,因为如果我们只有一个值,仍然可以调用一个接收者为指针类型的方法,这可以借助于Go语言传值的地址能力实现。

type Person struct{
    name string
    sex byte
    age int
}
//指针作为接收者,引用语义
func (p *Person) SetInfoPointer(){
    (*p).name="yoyo"
    p.sex='f'
    p.age=22
}
//值作为接收者,值语义
func (p Person)SetInfoValue(){
    p.name="xxx"
    p.sex='m'
    p.age=33
}
func main() {
    //p为普通值类型
    var p Person = Person{"mike",'m',18}
    (&p).SetInfoPointer()    //func(&p)SetInfoPointer()
    p.SetInfoPointer()    //func(&p)SetInfoPointer()
    p.SetInfoValue()    //func(p)SetInfoValue()
    (&p).SetInfoValue()    //func(*&p)SetInfoValue()
}

5匿名字段

5.1方法的继承

如果匿名字段实现了一个方法,那么包含这个匿名字段的struct也能调用该方法。

type Person struct {
    name string
    sex byte
    age int
}
//Person定义了方法
func (p *Person) PrintInfo() {
    fmt.Printf("%s,%c,%d\n",p.name,p.sex,p.age)
}
type Student struct {
    Person//匿名字段,那么Student包含了Person的所有字段
    id int
    addr string
}
func main() {
    p := Person{"mike",'m',18}
    p.PrintInfo()
    s := Student{Person{"yoyo",'f',20},2,"sz"}
    s.PrintInfo()
}

5.2方法的重写

type Person struct {
    name string
    sex byte
    age int
}
//Person定义了方法
func (p *Person) PrintInfo() {
    fmt.Printf("Person:%s,%c,%d\n",p.name,p.sex,p.age)
}
type Student struct {
    Person//匿名字段,那么Student包含了Person的所有字段
    id int
    addr string
}
//Student定义了方法
func (s *Student) PrintInfo() {
    fmt.Printf("Student:%s,%c,%d\n",s.name,s.sex,s.age)
}
func main() {
    p:=Person{"mike",'m',18}
    p.PrintInfo()    //Person:mike,m,18
    s:=Student{Person{"yoyo",'f',20},2,"sz"}
    s.PrintInfo()    //Student:yoyo,f,20
    s.Person.PrintInfo()    //Person:yoyo,f,20
}

6方法值和方法表达式

类似于我们可以对函数进行赋值和传递一样,方法也可以进行赋值和传递。

根据调用者不同,方法分为两种表现形式:方法值和方法表达式。两者都可像普通函数那样赋值和传参,区别在于方法值绑定实例,⽽方法表达式则须显式传参。

6.1方法值

type Person struct{
    name string
    sex byte
    age int
}
func (p *Person) PrintInfoPointer() {
    fmt.Printf("%p,%v\n",p,p)
}
func (p Person) PrintInfoValue(){
    fmt.Printf("%p,%v\n",&p,p)
}
func main() {
    p:=Person{"mike",'m',18}
    p.PrintInfoPointer()    //0xc0420023e0,&{mike 109 18}
    pFunc1:=p.PrintInfoPointer    //方法值,隐式传递 receiver
    pFunc1()    //0xc0420023e0,&{mike 109 18}
    pFunc2:=p.PrintInfoValue
    pFunc2()    //0xc042048420,{mike 109 18}
}

6.2方法表达式

type Person struct {
    name string
    sex byte
    age int
}
func (p *Person) PrintInfoPointer() {
    fmt.Printf("%p,%v\n",p,p)
}
func (p Person) PrintInfoValue() {
    fmt.Printf("%p,%v\n",&p,p)
}
func main() {
    p:=Person{"mike",'m',18}
    p.PrintInfoPointer()//0xc0420023e0,&{mike 109 18}
    //方法表达式,须显式传参
    //func pFunc1 (p *Person))
    pFunc1:=(*Person).PrintInfoPointer
    pFunc1(&p)    //0xc0420023e0,&{mike 109 18}
    pFunc2:=Person.PrintInfoValue
    pFunc2(p)    //0xc042002460,{mike 109 18}
}

以上就是go语言方法集以及为类型添加方法的示例解析的详细内容,更多关于go语言方法集类型添加方法的资料请关注编程网其它相关文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯