回答

收藏

“<type> 是指向接口的指针

技术问答 技术问答 295 人阅读 | 0 人回复 | 2023-09-12

我有这个问题,对我来说似乎有点奇怪。看看这段代码:+ }/ R0 K4 i2 i, R& E
    package coreinterfacestype FilterInterface interface    Filter(s *string) bool}type FieldFilter struct    Key string    Val string}func (ff *FieldFilter) Filter(s *string) bool    // Some code}type FilterMapInterface interface    AddFilter(f *FilterInterface) uuid.UUID         RemoveFilter(i uuid.UUID)                       GetFilterByID(i uuid.UUID) *FilterInterface}type FilterMap struct    mutex   sync.Mutex    Filters map[uuid.UUID]FilterInterface}func (fp *FilterMap) AddFilter(f *FilterInterface) uuid.UUID    // Some code}func (fp *FilterMap) RemoveFilter(i uuid.UUID)    // Some code}func (fp *FilterMap) GetFilterByID(i uuid.UUID) *FilterInterface    // Some code}
    % y  U( u+ ?  `) [% }' ]# ]/ }
在其他包里,我有以下代码:  g% o/ u1 H$ S* x9 j' Q
    7 f  c( M1 p* L& s2 O
  • func DoFilter()      fieldfilter := &coreinterfaces.FieldFilter{Key: "app",Val: "152511"}    filtermap := &coreinterfaces.FilterMap{}    _ = filtermap.AddFilter(fieldfilter) // 因为时不会接受提到的行,因为
    ) ?* u7 P! l* t, T9 ?& L. B
  • “不能在 fieldint.AddFilter 用于 的参数fieldfilter(类型 coreinterfaces.FieldFilter)作为类型 coreinterfaces.FilterInterface:*coreinterfaces.FilterInterface 是指向界面的指针,而不是界面& k3 H1 l1 B$ L( A) m$ s3 S: A
  • 但是,当代码改为:[code]func DoBid() error    bs := string(b)    var ifilterfield coreinterfaces.FilterInterface    fieldfilter := &coreinterfaces.FieldFilter{Key: "app",Val: "152511"}    ifilterfield = fieldfilter    filtermap := &coreinterfaces.FilterMap{}    _ = filtermap.AddFilter(&ifilterfield)}
    5 w/ h2 {0 h/ }2 O  h# v0 Z4 u0 q
在调试应用程序时,一切正常,似乎都包括在内
6 R) B/ s) u2 p7 C我对这个话题有点困惑。当查看其他博客文章和堆栈溢出线程讨论这个完全相同的问题(例如 - This或 This)由于 fieldfilter 和 fieldmap 被初始化为指向接口的指针,而不是接口。我不明白这里发生了什么。我需要改变它,这样我就不会声明 FieldInterface 并实现接口分配。必须有一种优雅的方式来做到这一点。5 `6 \7 g, g( a4 S, @# v7 x
                                                                9 B5 y# I6 ?+ S
    解决方案:                                                               
! x8 G4 X2 i7 K                                                                所以你在这里混淆了两个概念。指向结构的指针不同于指向的指针不同。接口可直接存储在结构体中或指向结构体的指针。在后一种情况下,口,而不是指向接口的指针。
5 d. N  i* K/ h
    type Fooer interface    Dummy()}type Foo struct{}func (f Foo) Dummy() {}func main()    var f1 Foo    var f2 *Foo = &Foo{}    DoFoo(f1)    DoFoo(f2)}func DoFoo(f Fooer)    fmt.Printf("[%T] % v\n",f,f)}
    " B- e" b* H. C/ H
输出:
: c& A5 ^$ I$ e% A
    [main.Foo] {}[*main.Foo] &{}
    ! H6 ~2 F  t8 b5 c
https://play.golang.org/p/I7H_pv5H3Xl
9 L+ Q$ B7 W1 W% d在这两种情况下,f变量 inDoFoo只是一个接口,而不是指向接口的指针。但在存储 时f2,接口持有指向Foo结构指针。
' z7 |! V8 |4 W, T+ U; ~7 s. a指向接口的指针几乎是没有用处。事实上,Go 在操作过程中,它被修改为几个版本,不会自动取消引用接口指针(正如它对结构指针所做的),以防止它们使用。在绝大多数情况下,指向接口的指针反映了对接口应该如何工作的误解。: Z/ {( g5 F/ ]; y
但是,接口是有限的。如果结构直接传输到接口,则只能使用这种类型(即,not )的值方法来实现接口。这是因为您在接口中存储了原始结构的副本,因此指针方法会产生意想不到的效果(即无法更改原始结构)。因此,默认的经验法则是指向结构的指针存储在接口中,除非有令人信服的理由不这样做。func (f Foo) Dummy()``func (f *Foo) Dummy()
- ~* Y' h8 f  ]. B特别是对于您的代码,如果您将 AddFilter 函数签名更改为:
- }3 K7 Z5 M/ V/ d# `* V# I8 v
    func (fp *FilterMap) AddFilter(f FilterInterface) uuid.UUID2 U) B, T, g! ]0 [9 @! j
和 GetFilterByID 签名:: C8 K8 J0 m! b1 D+ M1 u
    func (fp *FilterMap) GetFilterByID(i uuid.UUID) FilterInterface4 f! g3 g! E/ Y* C
您的代码将按预期工作。fieldfilter是 type *FieldFilter,它填充了FilterInterface因此,接口类型AddFilter会接受它。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则