文章目录
- GoLang之方法调用系列二
- 1.方法定义
- 2.值类型调用方法(值接收者)
- 3.指针类型调用方法(值接收者)
- 4.值类型调用方法(指针接受者)
- 5.指针类型调用方法(指针接收者)
- 6.四大方法接收者地址
- 6.调用函数(值接收者)
- 7.调用函数(指针接收者)
- 8.不同结构体可以定义相同方法
- 9.函数与与方法的区别
- 10.reflet.TypeOf验证方法是函数
GoLang之方法调用系列二
1.方法定义
func (recevier type) methodName(参数列表)(返回值列表){}
1.一个包含了接受者的函数,接受者可以是命名类型、结构体类型、指针;
2.只能为当前包内命名类型定义方法;
3.不支持方法重载,receiver 只是参数签名的组成部分;
4.Golang 方法总是绑定对象实例,并隐式将实例作为第一实参 (receiver);
5.参数 receiver 可任意命名,如方法中未曾使用 ,可省略参数名;
6.参数 receiver 类型可以是 T 或 *T ;
7.参数和返回值可以省略 ;
8.可用实例 value 或 pointer 调用全部方法,编译器自动转换
package main
type Test struct{}
// 无参数、无返回值
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 main() {}
package main
// 无参数、无返回值
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
}
func main() {}
2.值类型调用方法(值接收者)
a := A{name: “eggo”}
a.Name()//等效于A.Name(a)
type A struct {
name string
}
func (a A) Name() string {
a.name = "Hi!"
return a.name
}
func main() {
a := A{name: "eggo"}
//可用实例 value调用方法,编译器自动转换
a.Name()//等效于A.Name(a)
fmt.Println(a.name)//输出:aggo
}
//注意,当接受者不是一个指针时,该方法操作对应接受者的值的副本(意思就是即使你使用了指针调用函数,但是函数的接受者是值类型,所以函数内部操作还是对副本的操作,而不是指针操作
a.Name()等效于A.Name(a)
type A struct {
name string
}
func (a A) Name() string {
a.name = "Hi!" + a.name
return a.name
}
func main() {
a := A{name: "eggo"}
//不能写成fmt.Println(a.name(a))
//以下中a.Name()与A.Nmae(a)两种方式是一样的
fmt.Println(a.Name()) //输出:Hi!eggo
fmt.Println(A.Name(a)) //输出;Hi!eggo
}
type A struct {
name string
}
func (a A) Name() string {
a.name = "Hi!"
return a.name
}
func main() {
fmt.Println(A.Name(A{name: "eggo"})) //输出:Hi!
}
不对结构体初始化也照常可以调用方法
type Animal struct {
Age int
}
func (animal Animal) getName() string {
return "animal" //返回一个字符串
}
func main() {
var animal Animal
fmt.Println(animal.getName())
fmt.Println(person.getName())
}
3.指针类型调用方法(值接收者)
type A struct {
name string
}
func (a A) Name() string {
a.name = "Hi!"
return a.name
}
func main() {
a := A{name: "eggo"}
b := &a
//可用实例 pointer 调用全部方法,编译器自动转换
b.Name()//等效于:(*b).Name() ,A.Name(*b)
fmt.Println(a.name) //输出:eggo
}
//注意,当接受者不是一个指针时,该方法操作对应接受者的值的副本(意思就是即使你使用了指针调用函数,但是函数的接受者是值类型,所以函数内部操作还是对副本的操作,而不是指针操作。
b.Name()等效于(*b).Name()
type A struct {
name string
}
func (a A) Name() string {
a.name = "Hi!"
return a.name
}
func main() {
fmt.Println((A{name: "eggo"}).Name())//Hi!
}
b.Name()等效于A.Name(*b)
type A struct {
name string
}
func (a A) Name() string {
a.name = "Hi!"
return a.name
}
func main() {
a := A{name: "eggo"}
b := &a
A.Name(*b)
fmt.Println(a.name) //输出:eggo
}
以下的方式也算指针类型调用方法(值接收者)
type A struct {
name string
}
func (a A) Name() string {
a.name = "Hi!"
return a.name
}
func main() {
a := &A{name: "eggo"}
a.Name()
fmt.Println(a.name) //输出:eggo
}
4.值类型调用方法(指针接受者)
type A struct {
name string
}
func (a *A) Name() string {
a.name = "Hi!"
return a.name
}
func main() {
a := A{name: "eggo"}
a.Name()//等效于: (&a).Name() , (*A).Name(&a)
fmt.Println(a.name) //输出:Hi
}
//注意:当接受者是指针时,即使用值类型调用那么函数内部也是对指针的操作。
a.Name()等效于 (&a).Name()
type A struct {
name string
}
func (a *A) Name() string {
a.name = "Hi!"
return a.name
}
func main() {
fmt.Println((&A{name: "eggo"}).Name())//hi
}
a.Name()等效于: (*A).SetName(&a)
type A struct {
name string
}
func (a *A) Name() string {
a.name = "Hi!"
return a.name
}
func main() {
a := A{name: "eggo"}
(*A).Name(&a)
fmt.Println(a.name) //输出:Hi
}
5.指针类型调用方法(指针接收者)
type A struct {
name string
}
func (a *A) Name() string {
a.name = "Hi!"
return a.name
}
func main() {
a := A{name: "eggo"}
b := &a
b.Name()//等效于:(*A).Name(b)
fmt.Println(a.name) //输出:Hi
}
b.Name()//等效于(*A).Name(b)
type A struct {
name string
}
func (a *A) Name() string {
a.name = "Hi!"
return a.name
}
func main() {
a := A{name: "eggo"}
b := &a
(*A).Name(b)
fmt.Println(a.name) //输出:Hi
}
type A struct {
name string
}
func (a *A) Name() string {
a.name = "Hi!"
return a.name
}
func main() {
fmt.Println((*A).Name(&A{name: "eggo"}))//Hi!
}
以下的方式也算指针类型调用方法(指针接收者)
type A struct {
name string
}
func (a *A) Name() string {
a.name = "Hi!"
return a.name
}
func main() {
a := &A{name: "eggo"}
a.Name()
fmt.Println(a.name) //输出:Hi
}
6.四大方法接收者地址
type Data struct {
x int
}
func (self Data) ValueTest() { // func ValueTest(self Data);
fmt.Printf("Value: %p\n", &self)
}
func (self *Data) PointerTest() { // func PointerTest(self *Data);
fmt.Printf("Pointer: %p\n", self)
}
func main() {
d := Data{}
p := &d
fmt.Printf("Data: %p\n", p) //d的地址,Data: 0xc000016098
fmt.Printf("Data: %p\n", &p) //p的地址
//d的地址
d.ValueTest() // 副本的地址, Value: 0xc0000160b8
p.ValueTest() // 副本的地址, Value: 0xc0000160d0
d.PointerTest() // d的地址, Pointer: 0xc000016098
p.PointerTest() // d的地址, Pointer: 0xc000016098
}
6.调用函数(值接收者)
//接收值类型参数的函数
func valueIntTest(a int) int {
return a + 10
}
func main() {
a := 2
fmt.Println("valueIntTest:", valueIntTest(a))
//函数的参数为值类型,则不能直接将指针作为参数传递
//fmt.Println("valueIntTest:", valueIntTest(&a))
//compile error: cannot use &a (type *int) as type int in function argument
}
7.调用函数(指针接收者)
//接收指针类型参数的函数
func pointerIntTest(a *int) int {
return *a + 10
}
func main() {
b := 5
fmt.Println("pointerIntTest:", pointerIntTest(&b))
//同样,当函数的参数为指针类型时,也不能直接将值类型作为参数传递
//fmt.Println("pointerIntTest:", pointerIntTest(b))
//compile error:cannot use b (type int) as type *int in function argument
}
8.不同结构体可以定义相同方法
type Human struct {
name string
}
type Student struct {
speciality string
}
func (s Student) demo1() {
fmt.Println("ssssssssssssss")
}
func (h Human) demo1() {
fmt.Println("hhhhhhhhhh")
}
func main() {
a := Human{}
b := Student{}
a.demo1()//hhhhhhhhhh
b.demo1()//sssssssssssssss
}
9.函数与与方法的区别
普通函数与方法的区别:
1.对于普通函数,接收者为值类型时,不能将指针类型的数据直接传递,反之亦然;
2.对于方法(如struct的方法),接收者为值类型时,可以直接用指针类型的变量调用方法,反过来同样也可以
10.reflet.TypeOf验证方法是函数
A.Nme(a)里的a就是所谓的方法接收者,它会作为方法Nme的以一个参数传入,这一点我们可以通过代码验证一下;
Go语言中函数类型只和参数与返回值相关,方法其实就是普通的函数,而接收者就是隐含的第一个参数
type A struct {
name string
}
func (a A) Name() string {
a.name = "Hi!" + a.name
return a.name
}
func Name(a A) string {
a.name = "Hi!" + a.name
return a.name
}
func main() {
t1 := reflect.TypeOf(A.Name)
t2 := reflect.TypeOf(Name)
fmt.Println(t1 == t2)//true
}