方法method

Go语言中函数是非常重要的,这点和C语言类似,但是又比C语言灵活的多。

method,一般翻译为方法,我也采用这种翻译。Go 语言中同时有函数和方法。一个方法就是一个包含了接受者的函数,接受者可以是命名类型或者结构体类型的一个值或者是一个指针。所有给定类型的方法属于该类型的方法集。

1、method和function的关系:

Go 方法是作用在接收者(receiver)上的一个函数,接收者是某种类型的变量。因此方法是一种特殊类型的函数。(a Go method is a function that acts onvariable of a certain type, called the receiver. So a method is a specialkindof function. —-摘自《The Way to Go》)

method是针对某一类型定义的function,

function可以单独调用,method必须针对某一类型的实例进行调用。

//function 调用方式
package.FuncName()

//method 调用方式
var t package.Type
t.MethodName()
2、method和function的定义
code

红色的func是定义函数的关键字,是不可变的,绿色部分是可选的,当然,如果有这部分,那就不是个函数了,而是一个方法(method)。这个方法只用于这个struct type的实例。蓝色部分是参数部分,参数可以没有但是()不能够省略。黄色部分也是可选的,如果有的话代表的是函数的返回值。这个位置有点奇怪,我们熟悉的语言,不管是java还是C,都会把返回值放在函数名前边,go却把它放到了最后。还有,go中的函数可以有0-n个返回值,并且可以指定返回值的名字。

pro4_2_1.go

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. type Person struct {
  6. Name string
  7. Age int
  8. }
  9. // @Description show person's message
  10. // @Param name string
  11. // @Param age int
  12. func (student *Person) show(name string, age int) {
  13. student.Name = name
  14. student.Age = age
  15. fmt.Printf("name: %s , Age: %d\r\n", student.Name, student.Age)
  16. }
  17. func main() {
  18. var p Person
  19. p.show("Bell", 42)
  20. }

3、为普通类型添加method:

go语言不允许为简单的基础类型添加method,如:

  1. func (t int) myadd(i, j int) int {
  2. return i + j
  3. }

编译器会提示:cannot define new methods on non-local type int

不过,通过go语言中的type,我们可以临时定义一个和int具有同样功能的类型(注意,go中用type定义的类型,和C中不一样的一点是,这新定义的类型和原来的类型属于不同的类型,不能直接相互赋值)。

然后对新定义的类型添加方法:

pro4_2_2.go

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. type Int int
  6. func (t *Int) myadd(i, j int) int {
  7. return i + j
  8. }
  9. func main() {
  10. var t Int
  11. fmt.Println(t.myadd(1, 2))
  12. }
为struct添加String方法

03.7结构体类型struct我提到过如果你写了struct,其实默认你应该实现一个String方法,这个方法类似于java里面的toString,这个方法是为了默认输出使用的。

现在我就来详细的解释一下。在那一节我们将结构体的时候有一个例子:
pro4_2_3.go

  1. type Person struct {
  2. Name string
  3. Age int
  4. }
  5. func main() {
  6. sunny := new(Person) //如果调用重写的String()方法需要使用这种定义方式。
  7. sunny.Name = "sunny"
  8. sunny.Age = 41
  9. fmt.Println(sunny)
  10. }

输出结果是:
&{sunny 41}
fmt.Printf(“Person:%v”, sunny)已经给出了一个默认的输出结果,不过我们要是希望输出结果更符合我们的要求,我们就需要对这个方法进行重写。重写如下:

  1. func (this *Person) String() string {
  2. return "(名字:" + this.Name + "\t年龄:" + strconv.Itoa(this.Age) + ")\r\n"
  3. }
  4. fmt.Println(sunny)

输出结果是:
(名字:sunny 年龄:41)

是不是感觉更一目了然,如果还不满意,你可以随意修改,修改成一种可阅读性和打印性的输出。

不要在 String() 方法里面调用涉及 String() 方法的方法,它会导致意料之外的错误,见下例:

pro4_2_4.go

  1. func (this *Person) String() string {
  2. return fmt.Sprintf("%v", this)
  3. }