Go方法总是绑定对象实例,并隐式将实例作为第一实参。
- 只能为当前包内命名的类型 定义方法
- 参数可任意命名,如果方法中未曾使用,可省略参数名
- 参数类型可以是T或*T,基类型T不能是接口或指针
- 不支持方法重载
- 可用实例调用全部方法,编译器自动转换
一个方法就是一个包含了接受者的函数,接受者可以是命名类型或者结构体类型的一个值或者一个指针。所有给定类型的方法属于该类型的方法集。
方法定义
func (recevier type) methodName(参数列表) (返回值列表) { 函数体 } 参数与返回值,可以省略
// 无参数、无返回值 func (t Test) method0() { } // 单参数、无返回值 func (t Test) method1(i int) { } // 多参数、无返回值 func (t Test) method2(x, y int) { } // 无参数、单返回值 func (t Test) method3() (i int) { return } // 多参数、多返回值 func (t Test) method4(x, y int) (z int, err error) { return } // 无参数、无返回值 func (t *Test) method5() { } // 单参数、无返回值 func (t *Test) method6(i int) { } // 多参数、无返回值 func (t *Test) method7(x, y int) { } // 无参数、单返回值 func (t *Test) method8() (i int) { return } // 多参数、多返回值 func (t *Test) method9(x, y int) (z int, err error) { return }
结构体类型和该类型的一个方法:
package main import ( "fmt" ) //结构体 type User struct { Name string Email string } //方法 func (u User) Notify() { fmt.Printf("%v : %v ", u.Name, u.Email) } func main() { // 值类型调用方法 u1 := User{"golang", "golang@golang.com"} u1.Notify() // 指针类型调用方法 u2 := User{"go", "go@go.com"} u3 := &u2 u3.Notify() } // golang : golang@golang.com // go : go@go.com
解释:我们首先定义了一个叫做User的结构体类型,然后定义了一个该类型的方法叫做Notify,该方法的接受者是一个User类型的值。要调用Notify方法,我们需要一个User类型的值或指针。
在这个例子中当我们使用指针时,Go调整和解引用指针使得调用可以被执行。注意,当接受者不是一个指针时,该方法操作对应接受者的值的副本。即使你使用了指针调用函数,但是函数的接受者是值类型,所以函数内部操作还是对副本的操作,而不是指针操作。
修改Notify方法,让它的接受者使用指针类型。
package main import ( "fmt" ) //结构体 type User struct { Name string Email string } //方法 func (u *User) Notify() { fmt.Printf("%v : %v ", u.Name, u.Email) } func main() { // 值类型调用方法 u1 := User{"golang", "golang@golang.com"} u1.Notify() // 指针类型调用方法 u2 := User{"go", "go@go.com"} u3 := &u2 u3.Notify() } // golang : golang@golang.com // go : go@go.com
注意:当接受者是指针时,即使用值类型调用那么函数内部也是对指针的操作。
方法不过是一种特殊的函数,只需将其还原,就知道receiver 和 *T 的区别。