golang结构体方法隐式调用

方法

方法是golang中的一个特性,方法可以看作是带有特殊接受者参数的函数,最常用的是为结构体定义方法,看起来就像面向对象里边的对象下的方法

package main

import (
	"fmt"
)

type Book struct{}

func (b Book) SetPages() {
	fmt.Println("SetPages")
}

func (b *Book) Pages() {
	fmt.Println("Pages")
}

如示例,是为Book类型定义了SetPages方法、为*Book类型定义了Pages方法,既可以为指针定义方法,也可以为值类型定义方法,方法是带有特殊接收者参数的函数,所以上边定义与如下是相同的:

func  Book.SetPages(b Book) {
	fmt.Println("SetPages")
}

func (*Book).Pages() {
	fmt.Println("Pages")
}

但是在定义时是不合法的,没法这么定义,但是我们可以显式调用隐式定义

func (b Book) SetPages() {
	fmt.Println("SetPages")
}

func (b *Book) Pages() {
	fmt.Println("Pages")
}

func main() {
	var b Book
	Book.SetPages(b)  // 显式调用
	(*Book).Pages(&b) // 显式调用
}

方法调用

调用方法时我们可以像面向对象调用对象下的方法一样,使用v.m的形式

type Book struct{}

func (b Book) SetPages() {
	fmt.Println("SetPages")
}

func (b *Book) Pages() {
	fmt.Println("Pages")
}

func main() {
	b := Book{}
	b1 := &b

	b.SetPages()  // SetPages
	b1.SetPages() // SetPages

	b.Pages()  // Pages
	b1.Pages() // Pages
}

为什么可以使用指针调用SetPages方法、值类型调用Pages方法呢?并没有为指针定义SetPages方法,也没有为值定义Pages方法啊。
原因在于golang为了方便,在设计的时候有考虑到,实际在使用指针调用SetPages方法时,golang会将其解释为*b1.SetPages()在使用值类型调用Pages方法时,golang会将其解释为&b.Pages()

如果我们这样写呢?

func (b Book) SetPages() {
	fmt.Println("SetPages")
}

func (b *Book) Pages() {
	fmt.Println("Pages")
}

func main() {

	(Book{}).SetPages()  // SetPages
	(&Book{}).SetPages() // SetPages

	(&Book{}).Pages() // Pages
	(Book{}).Pages()  // 报错
}

会发现调用(Book{}).Pages()会报错:

.\default.go:23:10: cannot call pointer method on Book literal

不能在字面量上调用指针方法,为什么不可以呢?和用变量调用的区别在哪呢?

原因

原因在于当接收者参数为指针类型时,接受者必须为可寻址的值类型,字面量结构体就是不可寻址的

func main() {

	(Book{}).SetPages()  // SetPages
	(&Book{}).SetPages() // SetPages

	(&Book{}).Pages() // Pages
	fmt.Printf("地址为:%p\n", Book{})// 地址为:%!p(main.Book={})
}

返回值不是一个地址
在golang种具有&T{}语法糖,与temp:=T{};(&temp)相同,所以&T{}可寻址不代表T{}可寻址

参考资料

golang不可寻址
go101

总结

以下情况可取地址操作

  1. 变量
  2. 可寻址的数组元素
  3. 可寻址的结构体字段
  4. 切片
  5. 指针引用
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值