目录

4.2 方法 method

优质
小牛编辑
134浏览
2023-12-01

方法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

package main

import (
    "fmt"
)

type Person struct {
    Name string
    Age  int
}

// @Description show person's message
// @Param    name  string
// @Param    age  int

func (student *Person) show(name string, age int) {
    student.Name = name
    student.Age = age
    fmt.Printf("name: %s , Age: %d\r\n", student.Name, student.Age)
}

func main() {
    var p Person
    p.show("Bell", 42)
}

3、为普通类型添加method:

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

func (t int) myadd(i, j int) int {

    return i + j

}

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

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

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

pro4_2_2.go

package main

import (
    "fmt"
)

type Int int

func (t *Int) myadd(i, j int) int {

    return i + j

}
func main() {
    var t Int
    fmt.Println(t.myadd(1, 2))
}
为struct添加String方法

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

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

type Person struct {
    Name string
    Age  int
}

func main() {
    sunny := new(Person)  //如果调用重写的String()方法需要使用这种定义方式。
    sunny.Name = "sunny"
    sunny.Age = 41
    fmt.Println(sunny)
}

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

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

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

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

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

pro4_2_4.go

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