Golang中这类函数的作用是什么?求大神解答

Golang中这类函数的作用是什么?求大神解答 我难以理解这个函数的执行流程。

  1. 这个“内部”函数是一个匿名函数吗?只是想确认一下术语是否正确。
  2. NewHandler 函数应该返回一个 sdk.Handler 类型的对象,对吗?但内部函数返回的是一个指向 sdk.Result 的指针和一个错误对象。我不明白那里发生了什么,*sdk.Result, error 怎么能作为一个单一的(并且是不同类型的)sdk.Handler 被返回呢?
func NewHandler(keeper Keeper) sdk.Handler {
	return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
		switch msg := msg.(type) {
		case MsgSetName:
			return handleMsgSetName(ctx, keeper, msg)
		default:
			return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, fmt.Sprintf("Unrecognized nameservice Msg type: %v", msg.Type()))
		}
	}
}

sdk.Handler 的定义在这里供参考:cosmos-sdk/types/handler.go at v0.38.2 · cosmos/cosmos-sdk · GitHub

type Handler func(ctx Context, msg Msg) (*Result, error)

我知道代码本身肯定是正确的,我只是不理解这是如何工作的,也不确定正确的术语是什么,以便能够查找相关信息。


更多关于Golang中这类函数的作用是什么?求大神解答的实战教程也可以访问 https://www.itying.com/category-94-b0.html

3 回复

谢谢 @laiboonh

更多关于Golang中这类函数的作用是什么?求大神解答的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


  1. 你也可以将其理解为闭包。https://tour.golang.org/moretypes/25
  2. 我将 func(ctx Context, msg Msg) (*Result, error) 解读为一个返回 (*Result, error) 的函数。因此 type Handler func(ctx Context, msg Msg) (*Result, error) 只是该函数的类型别名。所以 func NewHandler(keeper Keeper) sdk.Handler {...} 是一个名为 NewHandler 的函数,它返回一个 Handler

这是一个典型的Go语言高阶函数用法。NewHandler返回的是一个函数值,这个函数值符合sdk.Handler类型定义。

  1. 关于匿名函数:是的,return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { ... }返回的是一个匿名函数(函数字面量)。

  2. 关于类型匹配sdk.Handler本身就是一个函数类型:

type Handler func(ctx Context, msg Msg) (*Result, error)

所以NewHandler返回的函数完全匹配这个类型签名。

让我用一个更简单的例子说明:

package main

import "fmt"

// 定义函数类型
type Handler func(int, string) (string, error)

// 返回Handler类型的函数
func NewHandler() Handler {
    return func(x int, s string) (string, error) {
        if x > 0 {
            return fmt.Sprintf("Positive: %s", s), nil
        }
        return "", fmt.Errorf("negative number")
    }
}

func main() {
    handler := NewHandler()
    
    // 调用返回的函数
    result, err := handler(5, "test")
    if err != nil {
        fmt.Println("Error:", err)
    } else {
        fmt.Println("Result:", result) // 输出: Result: Positive: test
    }
}

在你的代码中,NewHandler返回的匿名函数:

  • 接收ctx sdk.Contextmsg sdk.Msg参数
  • 返回(*sdk.Result, error)
  • 这完全匹配sdk.Handler类型的定义

这种模式在Go中很常见,特别是在需要创建闭包(捕获外部变量keeper)或实现中间件模式时。keeper参数被匿名函数捕获,形成了闭包,所以返回的函数可以访问keeper变量。

执行流程:

  1. 调用NewHandler(keeper)返回一个函数
  2. 后续可以调用这个返回的函数:handler(ctx, msg)
  3. 函数内部根据msg的具体类型进行路由处理

这就是为什么*sdk.Result, error能作为sdk.Handler返回的原因——sdk.Handler本身就是返回这两个值的函数类型。

回到顶部