You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Go中实现Python的mock.ANY功能?

在Go中用cmp包实现类似Python mock.ANY的字典字段忽略匹配

在比较字典时忽略指定字段的值,Python里用mock.ANY就能轻松实现,示例代码如下:

from unittest.mock import ANY
actual = {'userName':'bob', 'lastModified':'2012-01-01'}
expected = {'userName':'bob', 'lastModified': ANY}
assert actual == expected

我尝试用Go的cmp包(支持自定义Equal方法)实现同样的功能,但代码跑不起来。问题应该是自定义的MatchAll类型没法和string类型正常匹配,求解决办法?我的尝试代码如下:

package main

import (
    "fmt"

    "github.com/google/go-cmp/cmp"
)

type MatchAll string

func (m MatchAll) Equal(v string) bool {
    return true
}

func main() { 
    matchAll := MatchAll("bruh")
    actual := map[string]any{
        "key": matchAll,
    }

    expected := map[string]any{
        "key": "foobar",
    }

    fmt.Println(cmp.Equal(expected, actual))
}

解决办法

问题核心是cmp包的Equal方法是双向匹配的,你定义的MatchAll的Equal方法只处理了和string的单向比较,而且字典value是any类型时,cmp不会自动处理跨类型的匹配逻辑。正确的做法是用cmp.Option自定义比较规则,或者给MatchAll实现通用的Equal方法。

方案一:自定义比较器(Comparer)

package main

import (
    "fmt"

    "github.com/google/go-cmp/cmp"
)

// 标记类型,表示匹配任意值
type MatchAll struct{}

// 自定义比较器:只要其中一个值是MatchAll,就判定为相等
func matchAny(v1, v2 any) bool {
    _, isMatch1 := v1.(MatchAll)
    _, isMatch2 := v2.(MatchAll)
    return isMatch1 || isMatch2
}

func main() {
    actual := map[string]any{
        "userName":     "bob",
        "lastModified": "2012-01-01",
    }

    expected := map[string]any{
        "userName":     "bob",
        "lastModified": MatchAll{},
    }

    // 传入自定义比较器作为cmp的选项
    fmt.Println(cmp.Equal(expected, actual, cmp.Comparer(matchAny))) // 输出true
}

方案二:给MatchAll实现通用Equal方法

如果把MatchAll定义为导出类型(首字母大写),可以直接实现Equal方法让cmp识别:

package main

import (
    "fmt"

    "github.com/google/go-cmp/cmp"
)

// 导出的MatchAll类型,用于匹配任意值
type MatchAll struct{}

// Equal方法:匹配任意类型的值都返回true
func (m MatchAll) Equal(_ any) bool {
    return true
}

func main() {
    actual := map[string]any{
        "userName":     "bob",
        "lastModified": "2012-01-01",
        "age":          30,
    }

    expected := map[string]any{
        "userName":     "bob",
        "lastModified": MatchAll{},
        "age":          MatchAll{},
    }

    // 因为MatchAll是导出类型,无需额外配置即可生效
    fmt.Println(cmp.Equal(expected, actual)) // 输出true
}

如果是未导出类型,需要加上cmp.AllowUnexported(MatchAll{})作为选项传入cmp.Equal。


内容的提问来源于stack exchange,提问作者Dracula

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 00:10:57