方法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的定义
红色的func是定义函数的关键字,是不可变的,绿色部分是可选的,当然,如果有这部分,那就不是个函数了,而是一个方法(method)。这个方法只用于这个struct type的实例。蓝色部分是参数部分,参数可以没有但是()不能够省略。黄色部分也是可选的,如果有的话代表的是函数的返回值。这个位置有点奇怪,我们熟悉的语言,不管是java还是C,都会把返回值放在函数名前边,go却把它放到了最后。还有,go中的函数可以有0-n个返回值,并且可以指定返回值的名字。
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中不一样的一点是,这新定义的类型和原来的类型属于不同的类型,不能直接相互赋值)。
然后对新定义的类型添加方法:
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() 方法的方法,它会导致意料之外的错误,见下例:
func (this *Person) String() string {
return fmt.Sprintf("%v", this)
}