请教一个 golang 接口方法设计的问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zzyphp111
V2EX    问与答

请教一个 golang 接口方法设计的问题

  •  
      zzyphp111 2021-08-14 21:25:32 +08:00 2406 次点击
    这是一个创建于 1567 天前的主题,其中的信息可能已经有所发展或是发生改变。

    背景 :通过断言是怎么实现接口实例化注入

    疑问的关键代码:

    var _ log.Logger = (*stdLogger)(nil) 

    提出疑问:

    首先有这样一个结构,表示 log 结构器

     // Logger is a logger interface. type Logger interface { Log(level Level, keyvals ...interface{}) error } 

    接下来按照正规流程,就是利用这个 logger 器,做些初始化 log 的方法

     var _ Logger = (*stdLogger)(nil) type stdLogger struct { log *log.Logger pool *sync.Pool } // NewStdLogger new a logger with writer. func NewStdLogger(w io.Writer) Logger { return &stdLogger{ log: log.New(w, "", 0), pool: &sync.Pool{ New: func() interface{} { return new(bytes.Buffer) }, }, } } 

    问题就在这里为什么,明明这个 new 方法返回的是 stdLogger 这个结构,而为啥返回类型是 Logger,我发现个特别点就是第一行做了断言处理,这个是什么原理,一般断言也是把已知结构转成明确固定结构,为啥这里明明 stdLogger 结构体和 Logger 结构体完全不一样,就可以实现断言?

    望大家不吝赐教,多多指出,或相关代码实现,本人对接口实现方面比较小白。

    15 条回复    2022-11-16 17:26:35 +08:00
    johnwood
        1
    johnwood  
       2021-08-14 21:34:52 +08:00
    golang 的类型系统和 java 之类的不一样,他是鸭子类型系统,结构不用明确表明自己实现了某个接口,也没有 java 那样的“继承”。go 的倾向是组合优于继承。

    回到问题,估计因为 stdLogger 里有嵌入的 log *log.Logger
    zzyphp111
        2
    zzyphp111  
    OP
       2021-08-14 21:40:22 +08:00
    zzyphp111
        3
    zzyphp111  
    OP
       2021-08-14 22:42:33 +08:00
    @johnwood #1 这也是我所以疑问的,你看 zap 的引入就没有嵌入 log *log.Logger,但也断言成功了,这是为什么 https://github.com/go-kratos/kratos/blob/main/examples/log/zap.go
    gjquoiai
        4
    gjquoiai  
       2021-08-14 22:57:21 +08:00
    一个编译时检查某个东西是否实现了某个接口的技巧,现在用的不多了,都用 linter 了
    johnwood
        5
    johnwood  
       2021-08-14 23:23:56 +08:00
    @zzyphp111 你看#3 连接的 16 行 有嵌入自己的实现的 logger
    comwrg
        6
    comwrg  
       2021-08-14 23:25:06 +08:00
    4L 说的对,是用来编译期保证正确的实现了某个接口,而不是等着运行之后程序 panic
    EscYezi
        7
    EscYezi  
       2021-08-15 00:05:03 +08:00 via iPhone
    只要实现了 Logger 所有的方法就实现了 Logger 接口
    楼主提到的 stdLogger 和 zapLogger 可以断言成功是因为两个结构体都实现了 Logger 接口的 Log 方法,和内嵌的那个 log 成员没关系
    johnwood
        8
    johnwood  
       2021-08-15 00:12:45 +08:00
    @EscYezi 你看 NewStdLogger 实例化的是什么
    EscYezi
        9
    EscYezi  
       2021-08-15 00:18:07 +08:00 via iPhone
    @johnwood #8 实例化的 stdLogger 啊,stdLogger 实现了 Logger 接口
    EscYezi
        10
    EscYezi  
       2021-08-15 00:52:54 +08:00
    可以尝试运行一下这段代码


    package main

    import "fmt"

    type Logger interface {
    Log(...interface{})
    }
    type myLogger struct {
    }

    func (l *myLogger) Log(...interface{}) {
    fmt.Println("my logger")
    }
    func main() {
    var l Logger = (*myLogger)(nil)
    l.Log("aaa")
    }
    johnwood
        11
    johnwood  
       2021-08-15 10:44:37 +08:00
    @EscYezi 看了 2 楼的连接 你说的对 stdLogger 实现了 Logger 接口
    zzyphp111
        12
    zzyphp111  
    OP
       2021-08-15 12:14:50 +08:00
    @EscYezi #10 嗯嗯,看了你的,感觉非常直观,也解决了我的疑问, 只要存在这个结构体的实现 就可以断言成功。

    感谢
    kksco
        13
    kksco  
       2021-08-16 13:53:49 +08:00   1
    zzyphp111
        14
    zzyphp111  
    OP
       2021-08-16 14:26:42 +08:00
    @kksco #13 非常感谢
    Ansen
        15
    Ansen  
       2022-11-16 17:26:35 +08:00
    我也在这里迷糊了,搜索到这帖子了

    然后学习群的群友推荐了这篇文章,看完茅塞顿开

    https://go-kratos.dev/en/blog/
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1055 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 23:49 PVG 07:49 LAX 15:49 JFK 18:49
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86