GoLang之方法调用系列二

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
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GoGo在努力

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值