这篇说下 go 的一个很重要的技巧,在包装一些链式 API 的时候很实用。
现在用 zerolog 举例,zerolog 是个用法很简单的结构化日志库,性能不错。通过下面的例子感受下用法。
package main
import (
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)
func main() {
log.Debug().
Str("Scale", "833 cents").
Float64("Interval", 833.09).
Msg("Fibonacci is everywhere")
}
// Output:
// {"level":"debug","Scale":"833 cents","Interval":833.09,"message":"Fibonacci is everywhere"}
想在 zerolog 的链式 API 加入 ID 函数,还能继承原有的一堆 API,比如.ID("1234") 会在 json 字段里面插入{"ID":"1234"}
package main
import (
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)
func main() {
log.Debug().ID("request id")
Str("Scale", "833 cents").
Float64("Interval", 833.09).
Msg("Fibonacci is everywhere")
}
// Output: {"level":"debug","Scale":"833 cents","Interval":833.09,"message":"Fibonacci is everywhere"}
加上一短代码
func (e *zerolog.Event) ID(id string) *zerolog.Event {
e.Str("ID", id)
return e
}
// 输出
// ./wenti.go:9:6: cannot define new methods on non-local type zerolog.Event
// ./wenti.go:16:13: log.Debug().ID undefined (type *zerolog.Event has no field or method ID)
触发了编译器限制,这条路走不通。
go 是没有语法上的继承的,只有组合。结构提内嵌可以实现方法的继承,在结构提里面写过 sync.Mutex 的都知道。
type Stats struct {
sync.Mutex
}
func (s *Stats) Snapshot() map[string]int {
s.Lock()
defer s.Unlock()
}
使用匿名结构体嵌套,实现方法的复用。
type event struct {
*zerolog.Event
}
func (e *event) ID(id string) *event {
return &event{e.Str("ID", id)}
}
package main
import (
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)
type Ulog struct {
zerolog.Logger
}
func (u *Ulog) Debug() *event {
return &event{u.Logger.Debug()}
}
func (u *Ulog) Info() *event {
return &event{u.Logger.Info()}
}
func (u *Ulog) Warn() *event {
return &event{u.Logger.Warn()}
}
func (u *Ulog) Error() *event {
return &event{u.Logger.Error()}
}
type event struct {
*zerolog.Event
}
func (e *event) ID(id string) *event {
return &event{e.Str("ID", id)}
}
func main() {
u := Ulog{Logger: log.Logger}
u.Debug().
ID("hello").
Str("Scale", "833 cents").
Float64("Interval", 833.09).
Msg("Fibonacci is everywhere")
}
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.