golang中关于map的value类型定义为函数类型时(方法值)的一点点思考

文章的内容仅仅是自己关于map的value类型定义为函数类型时的一点点思考,如有不对的地方,请不吝赐教。

学习过后才知道叫做 方法值

1、起因

最近在看老项目代码时,看到了一段类似于下面的定义,最开始看到的时候,对于 LotMap 的用法比较疑惑,为什么 map value 定义的函数类型是 func(r *Receiver, lot *Lot, msg *History),但是在初始化时,传递的值却是(*Receiver).handleStart

然后根据自己的有了下面的思考,如有不对,请多指教。

go 复制代码
package main

var LotMap = map[string]func(r *Receiver, lot *Lot, msg *History){
	"start": (*Receiver).handleStart,
	"end":   (*Receiver).handleEnd,
}

type Lot struct {
}

type History struct {
}

type Receiver struct{}

func (r *Receiver) handleStart(lot *Lot, msg *History) {

}

func (r *Receiver) handleEnd(lot *Lot, msg *History) {

}

func main() {
	r := &Receiver{}
	lot := &Lot{}
	msg := &History{}
	LotMap["start"](r, lot, msg)
}

2、原因

如果你有我一样的疑惑,接下来我们一起看看是为啥?

《go 语言圣经》中的第6.4. 方法值和方法表达式 有讲解关于方法值的介绍。

大家可以先去看看原文关于方法值 的介绍后,再来看本文。

说实话,我看了上面的文章中的介绍后,对于方法值还是一头雾水,不知道在讲什么。(怪我太菜)

接下来我按照自己的理解,说说对于方法值的理解。

2.1、什么叫方法值

在Go语言中,方法值(method value)指的是将方法绑定到特定接收者实例上,从而创建一个函数值(function value)。方法值允许你将方法视为普通函数,可以将其传递给其他函数或者存储在变量中,之后在不同的上下文中调用。

例如,如果有一个方法 func (r *Receiver) handleStart(lot *Lot, msg *History),你可以使用 (*Receiver).handleStart 创建一个方法值,然后将其传递给其他函数或存储在变量中,如下所示:

go 复制代码
// 方法值的创建
methodValue := (*Receiver).handleStart

// 将方法值传递给其他函数
someFunction(methodValue)

// 存储方法值到变量中
var myFunction func(r *Receiver, lot *Lot, msg *History)
myFunction = methodValue

在这里,methodValue 就是一个方法值,它与特定的接收者实例无关,可以在任何需要的地方使用,类似于普通的函数值。

2.2、 样例解释

看完了上面的的 何为方法值 后,相比应该对方法值有一定的了解,对于样例的用法,也熟悉了不少。

接下里,我们在 main 函数中加入下面的语句

go 复制代码
func main() {
	r := &Receiver{}
	lot := &Lot{}
	msg := &History{}
	LotMap["start"](r, lot, msg)

	fmt.Printf("%T\n", r.handleStart)
	fmt.Printf("%T\n", (*Receiver).handleStart)
}

运行结果:

func(*main.Lot, *main.History)
func(*main.Receiver, *main.Lot, *main.History)

如果将 LotMap 中的(*Receiver)变成(Receiver),ide 也会提示,提示如下:

所以方法值的本质是:编译器会将 (*Receiver).handleStart 变成 func(*Receiver, *Lot, *History)

3、总结

第一点:

上面的 LotMap 这种写法,其实有一个专用的词,叫做查找表。使用查找表可以避免了冗长的 if-else 或 switch-case 语句,使代码更加清晰、易于维护。

第二点:

在Go语言中,(*Receiver).handleStart这种形式是方法值(method value)的写法,可以将方法绑定到特定的接收者实例上,从而创建一个函数值(function value)。在这种写法中,方法接收者(receiver)会被作为第一个参数传递给方法。

因此,(*Receiver).handleStart可以转换为func(r *Receiver, lot *Lot, msg *History)的函数签名,其中r *Receiver就对应方法接收者,而lot *Lotmsg *History则是方法的其他参数。

这种转换允许将方法作为普通函数一样传递给其他函数或者存储在映射(map)中,使得代码更加灵活和易于组织。

相关推荐
技术卷16 分钟前
golang学习笔记4-基本数据类型
笔记·学习·golang
请不要叫我菜鸡1 小时前
Go语言基础学习02-命令源码文件;库源码文件;类型推断;变量重声明
linux·后端·golang·类型推断·短变量·变量重声明·库源码文件
jzpfbpx4 小时前
[go] 适配器模式
开发语言·golang·适配器模式
qq_1728055910 小时前
Go Testify学习与使用
开发语言·golang·go
多思考少编码13 小时前
【LGR-200-Div.4】洛谷入门赛 #27 A - H题解,包含(C++, Go语言)
开发语言·c++·golang·洛谷·算法竞赛
蒙娜丽宁14 小时前
深入理解Go语言中的接口定义与使用
开发语言·后端·golang·go
The Straggling Crow15 小时前
go 战略
开发语言·后端·golang
GoFly开发者18 小时前
GoFly快速开发框架/Go语言封装的图像相似性比较插件使用说明
开发语言·后端·golang
翔云12345619 小时前
Go语言的垃圾回收(GC)机制的迭代和优化历史
java·jvm·golang·gc
__AtYou__21 小时前
Golang | Leetcode Golang题解之第417题太平洋大西洋水流问题
leetcode·golang·题解