回答

收藏

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

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

我有这个问题,对我来说似乎有点奇怪。看看这段代码:, ]" f1 K, n- O- o3 o/ h
    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}4 j& [7 L7 t( C' r8 c
在其他包里,我有以下代码:7 \4 n# f. [' I3 u' Z: `6 z
    : J+ m$ k! _0 n' ]( v$ ?: p* }
  • func DoFilter()      fieldfilter := &coreinterfaces.FieldFilter{Key: "app",Val: "152511"}    filtermap := &coreinterfaces.FilterMap{}    _ = filtermap.AddFilter(fieldfilter) // 因为时不会接受提到的行,因为
    / D) `/ d( u) M
  • “不能在 fieldint.AddFilter 用于 的参数fieldfilter(类型 coreinterfaces.FieldFilter)作为类型 coreinterfaces.FilterInterface:*coreinterfaces.FilterInterface 是指向界面的指针,而不是界面& Q/ y; O* c, R" a, a& R
  • 但是,当代码改为:[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)}
    6 J! L' X6 Z! h" d! X
在调试应用程序时,一切正常,似乎都包括在内. o0 y( B! `5 J/ z" E# [
我对这个话题有点困惑。当查看其他博客文章和堆栈溢出线程讨论这个完全相同的问题(例如 - This或 This)由于 fieldfilter 和 fieldmap 被初始化为指向接口的指针,而不是接口。我不明白这里发生了什么。我需要改变它,这样我就不会声明 FieldInterface 并实现接口分配。必须有一种优雅的方式来做到这一点。
$ r7 d: M8 v1 I9 J                                                                9 \- q( R# R5 l+ \) G- s: @  @4 f9 e: O6 b
    解决方案:                                                                ! E. n1 _/ L: m, k5 e) m
                                                                所以你在这里混淆了两个概念。指向结构的指针不同于指向的指针不同。接口可直接存储在结构体中或指向结构体的指针。在后一种情况下,口,而不是指向接口的指针。
  ?9 @! ?: |1 h  s' b5 K
    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)}
    . `) k( }6 @6 G
输出:
( e/ p5 r. y6 e* U1 f
    [main.Foo] {}[*main.Foo] &{}8 X4 _5 ?0 p. C- a" k; p; ~% _& P
https://play.golang.org/p/I7H_pv5H3Xl
5 H8 C. K7 P2 C' W( C在这两种情况下,f变量 inDoFoo只是一个接口,而不是指向接口的指针。但在存储 时f2,接口持有指向Foo结构指针。( {( o2 f2 ?. W; @
指向接口的指针几乎是没有用处。事实上,Go 在操作过程中,它被修改为几个版本,不会自动取消引用接口指针(正如它对结构指针所做的),以防止它们使用。在绝大多数情况下,指向接口的指针反映了对接口应该如何工作的误解。* R+ o! G# N7 J
但是,接口是有限的。如果结构直接传输到接口,则只能使用这种类型(即,not )的值方法来实现接口。这是因为您在接口中存储了原始结构的副本,因此指针方法会产生意想不到的效果(即无法更改原始结构)。因此,默认的经验法则是指向结构的指针存储在接口中,除非有令人信服的理由不这样做。func (f Foo) Dummy()``func (f *Foo) Dummy()
$ P2 o: Z3 z% v0 ~  c特别是对于您的代码,如果您将 AddFilter 函数签名更改为:7 p1 v- I. u8 d7 u$ R
    func (fp *FilterMap) AddFilter(f FilterInterface) uuid.UUID8 u$ B2 w8 d  ]6 R5 P# Q/ k  N
和 GetFilterByID 签名:
# d) \% K6 u) {, u4 x& w
    func (fp *FilterMap) GetFilterByID(i uuid.UUID) FilterInterface' ?. I; r# B2 r* n: z
您的代码将按预期工作。fieldfilter是 type *FieldFilter,它填充了FilterInterface因此,接口类型AddFilter会接受它。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则