回答

收藏

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

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

我有这个问题,对我来说似乎有点奇怪。看看这段代码:
/ v4 o0 v8 ?, K1 T0 h9 w
    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}: x/ Q. R3 W1 l- a# {# K; b
在其他包里,我有以下代码:
# l' {2 o1 Y; g" e/ z' b( F
      s3 h: C( v; d2 ~# _6 u; J4 W' `
  • func DoFilter()      fieldfilter := &coreinterfaces.FieldFilter{Key: "app",Val: "152511"}    filtermap := &coreinterfaces.FilterMap{}    _ = filtermap.AddFilter(fieldfilter) // 因为时不会接受提到的行,因为
    $ q1 A$ e5 E9 A' x3 t3 l3 e' Y
  • “不能在 fieldint.AddFilter 用于 的参数fieldfilter(类型 coreinterfaces.FieldFilter)作为类型 coreinterfaces.FilterInterface:*coreinterfaces.FilterInterface 是指向界面的指针,而不是界面
    5 W) U6 a# X4 j' e4 J* b. w
  • 但是,当代码改为:[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)}8 ], T7 D+ I( B5 k
在调试应用程序时,一切正常,似乎都包括在内( x; x- S5 ]  L0 s
我对这个话题有点困惑。当查看其他博客文章和堆栈溢出线程讨论这个完全相同的问题(例如 - This或 This)由于 fieldfilter 和 fieldmap 被初始化为指向接口的指针,而不是接口。我不明白这里发生了什么。我需要改变它,这样我就不会声明 FieldInterface 并实现接口分配。必须有一种优雅的方式来做到这一点。
  K4 D1 J- o; H) N6 l* _) d                                                                . y( S$ K8 Z8 [# |' d1 r
    解决方案:                                                                1 v, c- u: P: K' g4 K& ~
                                                                所以你在这里混淆了两个概念。指向结构的指针不同于指向的指针不同。接口可直接存储在结构体中或指向结构体的指针。在后一种情况下,口,而不是指向接口的指针。; K  y! k( l/ `1 Z+ P: z
    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)}
      u. {; r+ c) T* ?
输出:, E! y. h! Z" L% p+ G
    [main.Foo] {}[*main.Foo] &{}
    & y& t% N3 t5 W. z! H- @$ ^
https://play.golang.org/p/I7H_pv5H3Xl4 T2 }- E2 i4 ~( i) p! J
在这两种情况下,f变量 inDoFoo只是一个接口,而不是指向接口的指针。但在存储 时f2,接口持有指向Foo结构指针。
! {3 r- C0 j& [" K% |; R指向接口的指针几乎是没有用处。事实上,Go 在操作过程中,它被修改为几个版本,不会自动取消引用接口指针(正如它对结构指针所做的),以防止它们使用。在绝大多数情况下,指向接口的指针反映了对接口应该如何工作的误解。
9 y4 x) D. N0 \# _5 D9 q3 \但是,接口是有限的。如果结构直接传输到接口,则只能使用这种类型(即,not )的值方法来实现接口。这是因为您在接口中存储了原始结构的副本,因此指针方法会产生意想不到的效果(即无法更改原始结构)。因此,默认的经验法则是指向结构的指针存储在接口中,除非有令人信服的理由不这样做。func (f Foo) Dummy()``func (f *Foo) Dummy()
/ S+ f, H- e4 M# [4 R% f* m* R特别是对于您的代码,如果您将 AddFilter 函数签名更改为:
" V& z! N+ t* d2 m2 ]
    func (fp *FilterMap) AddFilter(f FilterInterface) uuid.UUID
    6 ]* M9 J  W; s1 O4 G; {. r
和 GetFilterByID 签名:( U$ w+ a/ o4 v
    func (fp *FilterMap) GetFilterByID(i uuid.UUID) FilterInterface# A( T8 O1 {8 V9 r& F9 i2 B
您的代码将按预期工作。fieldfilter是 type *FieldFilter,它填充了FilterInterface因此,接口类型AddFilter会接受它。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则