golang 两个一样的字符串不相等_golang 函数和方法 , 有什么不一样?

本文介绍了Go语言中函数作为一等类型的特点,包括作为参数和返回值,以及如何创建闭包。同时,详细讨论了方法的概念,包括值方法和指针方法的区别,特别是接收者如何影响方法对源值的修改能力。通过示例展示了如何声明和使用方法,并解释了Go中自动转换规则以便在非指针类型上调用指针方法。
摘要由CSDN通过智能技术生成
d542a86ebd89923872df776895025db1.png

在Go中,函数类型是一等类型,这意味着可以把函数当作一个值来传递和使用。函

数值既可以作为其他函数的参数,也可以作为其结果。另外,我们还可以利用函数类型

的这一特性生成闭包。

一个函数的声明通常包括关键字func、函数名、分别由圆括号包裹的参数列表和结

果列表,以及由花括号包裹的函数体,就像这样:

func divide(dividend int,divisor int)(int,error){//省略部分代码}

函数可以没有参数列表,也可以没有结果列表,但空参数列表必须保留括号,而空

结果列表则不用,示例如下:

func printTab(){//省略部分代码

另外,参数列表中的参数必须有名称,而结果列表中结果的名称则可有可无。不过

结果列表中的结果要么都省略名称,要么都要有名称。带有结果名称的divide函数的声

明如下:

func divide(dividend int,divisor int)(result int,err error){//省略部分代码}

如果函数的结果有名称,那么在函数被调用时,以它们为名的变量就会被隐式声明。

如此一来在函数中就可以直接使用它们了,就像使用参数那样。给代表结果的变量赋值,

就相当于设置函数的返回结果。

a58f6e58d553c05d49971ff5c51ff1e2.png

函数体中每个条件分支的最后一般都要有return语句,该语句以return关键字开始,

后跟与函数结果列表相匹配的变量、常量、表达式或值。无论是什么,它们都会被求值

并得到确切的值。但是,如果函数声明的结果是有名称的,那么return关键字后面就不

用追加任何东西了。divide函数的完整声明可以这样:

func divide(dividend int,divisor int)(result int,err error){if divisor==0{err=errors.New("division by zero")returnresult=dividend/divisorreturn

其中,errors是一个标准库代码包的名称,而其中的New函数专用于生成error类型的值。

Go编程有一个惯用法,即把error类型的结果作为函数结果列表的最后一员。

当然,你可以编写自己的divide函数,不过在这之前需要把它提升成一个类型:

//用于定义二元操作的面数类型

type binaryoperation func(operandt int,operand2int)(result int,err error)

除法是一个二元操作,所以我做了进一步的范化。再编写一个函数,你就会知道这

样做的意义了:

//用于以自定义的方式执行二无操作func operate(op1 int,op2 int,bop binaryoperation)(result int,err error){if bop==nil{err=errors.New("invalid binary operation function")returnreturn bop(op1,op2)

这里实际上实现了一个闭包,我把二元操作的实现权留给了operate函数的使用者。

作为一等类型的函数类型让程序的灵活性大大增加,接口不再是定义行为的唯一途径了。

顺便说一句,函数类型的零值是ni1。检查外来函数值是否非ni1总是有必要的。

方法是函数的一种,它实际上就是与某个数据类型关联在一起的函数,示例如下:

type myInt intfunc(i myInt)add(another int)myInt{i=i+myInt(another)return i

从声明上看,方法只是在关键字func和函数名称之间,加了一个由圆括号包裹的接

收者声明。接收者声明由两部分组成:右边表明这个方法与哪个类型关联,这里是myInt;

左边指定这个类型的值在当前方法中的标识符,这里是i。这个标识符在当前方法中可以

看作一个变量的代表,就像参数那样。所以,它也可以称为接收者变量。不过这里有一

个问题,请看:

i1:=myInt(1)i2:=il.add(2)fmt.Print1n(i1,i2)

这3行代码执行后,会打印出13。i的值未改变,是因为在值方法中对接收者变量的赋

值一般不会影响到源值。这里,变量i1的值就是源值。在调用i1的add方法时,这个值

被赋给了接收者变量i(前者的副本与后者产生关联)。但是,i和i1是两个变量,它们

之间并不存在关联。

61861b4c2e7c19348860a926770b339e.png

值方法的接收者类型是非指针的数据类型。相对应的是指针方法。它的接收者类型

是某个数据类型的指针类型。若把add方法改造成指针方法,则可以是:

func(i*myInt)add(another int)myInt{*i=*i+myInt(another)return*i

这时add方法是myInt的指针方法。这里请注意操作符*的用法。*myInt表示了myInt的

指针类型,而*i则表示指针i指向的值。经改造,前面那3行代码的执行效果就会是打

值方法和指针方法遵循了如下规则。

接收者变量代表的值实际上是源值的一个复制品。如果这个值不是指针类型的,

那么在值方法中自然就没有途径去改变源值。而指针值与其复制品指向的肯定是

同一个值,所以在指针方法中就存在了改变源值的途径。这里有一个例外,那就

是如果接收者类型是某个引用类型或它的别名类型,那么即使是值方法,也可以

改变源值。

08a75011cae731c6dad8596628d13862.png

对于某个非指针的数据类型,与它关联的方法的集合中只包含它的值方法。而对

于它的指针类型,其方法集合中既包含值方法也包含指针方法。不过,在非指针

数据类型的值上,也是能够调用其指针方法的。这是因为Go在内部做了自动转换。

例如,若add方法是指针方法,那么表达式i1.add(2)会被自动转换为(8i1).add(2)。

请注意,第二条规则对于编写接口类型的实现类型来说非常有用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值