From a90823eba424c035b6af3fb361a86161ea5906f4 Mon Sep 17 00:00:00 2001 From: des <18638715007@163.com> Date: Tue, 24 Feb 2026 20:55:18 +0800 Subject: [PATCH] =?UTF-8?q?=E8=87=AA=E5=8A=A8=E6=9F=A5=E6=89=BE=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 但是自动收集到数组是个超级糟糕的需求。糟糕到我认为需要另起炉灶。 --- internal/wire/analyze.go | 2 ++ internal/wire/parse.go | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/internal/wire/analyze.go b/internal/wire/analyze.go index 9650ef1..957818f 100644 --- a/internal/wire/analyze.go +++ b/internal/wire/analyze.go @@ -329,6 +329,8 @@ func verifyArgsUsed(set *ProviderSet, used []*providerSetSrc) []error { // buildProviderMap creates the providerMap and srcMap fields for a given // provider set. The given provider set's providerMap and srcMap fields are // ignored. +// +// 这里就是查找注入的核心 func buildProviderMap(fset *token.FileSet, hasher typeutil.Hasher, set *ProviderSet) (*typeutil.Map, *typeutil.Map, []error) { providerMap := new(typeutil.Map) providerMap.SetHasher(hasher) diff --git a/internal/wire/parse.go b/internal/wire/parse.go index 09f1e1d..3b2a0a2 100644 --- a/internal/wire/parse.go +++ b/internal/wire/parse.go @@ -74,6 +74,7 @@ func (p *providerSetSrc) description(fset *token.FileSet, typ types.Type) string // trace returns a slice of strings describing the (possibly recursive) source // of p, including line numbers. +// 这里是 srcMap 唯一使用的地方,看起来似乎只是用作错误输出,应该不会干扰我的修改。 func (p *providerSetSrc) trace(fset *token.FileSet, typ types.Type) []string { var retval []string // Only Imports need recursion. @@ -122,12 +123,39 @@ func (set *ProviderSet) Outputs() []types.Type { } // For returns a ProvidedType for the given type, or the zero ProvidedType. +// 这个方法是我们改造的重点,两个功能都要从这个函数进行动作 +// - 自动查找所有接口的实现 +// +// 已知的困难是 +// +// 比如遇见一个新的接口,遍历所有 ProvidedType 进行检查并向 ProviderMap 中添加项以避免下次检查。 +// 但是如果有两个接口先后需要查找,此时第二次查找同样会遍历第一次查找生成的 ProviderType 数据。 +// 我想起来了,好像 ProviderSet 中有个 providers 属性储存了原始的那啥。可以使用这个遍历避免 ProviderType 膨胀问题 func (set *ProviderSet) For(t types.Type) ProvidedType { pt := set.providerMap.At(t) - if pt == nil { + if pt != nil { + return *pt.(*ProvidedType) + } + face, isFace := t.Underlying().(*types.Interface) + if !isFace { return ProvidedType{} } - return *pt.(*ProvidedType) + var addMap []ProvidedType + for _, provider := range set.Providers { + pro := types.Implements(provider.Out[0], face) + if pro { + addMap = append(addMap, ProvidedType{t: t, p: provider}) + } + } + if len(addMap) == 0 { + return ProvidedType{} + } else if len(addMap) == 1 { + provider := addMap[0] + set.providerMap.Set(t, &provider) + set.srcMap.Set(t, &providerSetSrc{Provider: provider.p}) + return provider + } + panic("接口 " + t.String() + " 拥有多个实现") } // An IfaceBinding declares that a type should be used to satisfy inputs @@ -1155,6 +1183,9 @@ func isProviderSetType(t types.Type) bool { // can be a *Provider (a provider function), a *Value (wire.Value), or an // *InjectorArgs (arguments to the injector function). The zero value has // none of the above, and returns true for IsNil. +// +// 在我的角度来看,这东西其实有点职责混淆。因为他还顺带兼任了判断类是否存在的功能。 +// 总之,这个结构体标记了提供者,还有一个检查是否有提供者的方法。当然,可能不止这一个功能。 type ProvidedType struct { // t is the provided concrete type. t types.Type