目录
1. Golang magic code 特殊用法 (With/Option/_()/不让比较/nocmp/reset slice)
Golang 有些写法比较怪异的, 这里记录一下。
1.1. 普通数据类型可以带方法
int 带方法:
type testint int
func (ti testint) ToString() string {
return "test_int"
}
func main() {
a := testint(2)
fmt.Println(a.ToString())
}
1.2. 验证某结构体是否已经实现某 interface 的所有方法
1.2.1. 方法一
// Make sure the SinkInfluxDB conforms with the sinkcommon.ISink interface
var _ sinkcommon.ISink = new(SinkInfluxDB)
type ISink interface {
GetInfo() *SinkInfo
LoadConfig(mConf map[string]interface{}) error
Write(pts []ISinkPoint) error
}
func (s *SinkInfluxDB) GetInfo() *sinkcommon.SinkInfo {
func (s *SinkInfluxDB) LoadConfig(mConf map[string]interface{}) error {
func (s *SinkInfluxDB) Write(pts []sinkcommon.ISinkPoint) error {
1.2.2. 方法二: func _()
是干嘛用的
同 var _ interface = new(StructName)
一样,一般用来做某种检测,例如判断结构体是不是实现了接口。
示例:
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[filterReleased-1]
_ = x[filterRefreshed-2]
}
1.2.3. 方法三
var _ interface = (*StructName)(nil)
1.3. struct 不让比较
// Uint64 is an atomic wrapper around uint64.
type Uint64 struct {
_ nocmp // disallow non-atomic comparison
v uint64
}
其中 nocmp
:
// nocmp is an uncomparable struct. Embed this inside another struct to make
// it uncomparable.
//
// type Foo struct {
// nocmp
// // ...
// }
//
// This DOES NOT:
//
// - Disallow shallow copies of structs
// - Disallow comparison of pointers to uncomparable structs
type nocmp [0]func()
[0]func()
的意思是: 定义一个长度为 0 的数组, 不占用空间。
Slice, map, and function values are not comparable. However, as a special case, a slice, map, or function value may be compared to the predeclared identifier nil. Comparison of pointer, channel, and interface values to nil is also allowed and follows from the general rules above. 即 slice
、map
、func
只能和 nil
比较。
1.4. reset slice
ps, _ := r.paramsPool.Get().(*Params)
*ps = (*ps)[0:0] // reset slice
return ps
1.5. With Options
1.5.1. interface
type FeederOutputer interface {
Write(data *iodata) error
WriteLastError(err string, opts ...LastErrorOption)
Reader(c point.Category) <-chan *iodata
}
1.5.2. var _ new
var _ FeederOutputer = new(datawayOutput)
// feederOutput send feeder data to dataway.
type datawayOutput struct {
chans map[string]chan *iodata
}
// WriteLastError send any error info into Prometheus metrics.
func (fo *datawayOutput) WriteLastError(err string, opts ...LastErrorOption) {
le := newLastError()
for _, opt := range opts {
if opt != nil {
opt(le)
}
}
catStr := point.SUnknownCategory
if len(le.Categories) == 1 {
catStr = le.Categories[0].String()
}
// make feed/last-feed entry for that source with category
// they must be real input, we need to take them out for latter
// use, such as get metric of only inputs.
inputsFeedVec.WithLabelValues(le.Source, catStr).Inc()
inputsLastFeedVec.WithLabelValues(le.Source, catStr).Set(float64(time.Now().Unix()))
errCountVec.WithLabelValues(le.Source, catStr).Inc()
lastErrVec.WithLabelValues(le.Input, le.Source, catStr, err).Set(float64(time.Now().Unix()))
}
1.5.3. option
type LastErrorOption func(*LastError)
type LastError struct {
Input, Source string
Categories []point.Category
}
const defaultInputSource = "not-set"
func newLastError() *LastError {
return &LastError{
Input: defaultInputSource,
Source: defaultInputSource,
}
}
func WithLastErrorInput(input string) LastErrorOption {
return func(le *LastError) {
le.Input = input
if len(le.Source) == 0 || le.Source == defaultInputSource { // If Source is empty, filling with Input.
le.Source = input
}
}
}
func WithLastErrorSource(source string) LastErrorOption {
return func(le *LastError) {
le.Source = source
if len(le.Input) == 0 || le.Input == defaultInputSource { // If Input is empty, filling with Source.
le.Input = source
}
}
}
func WithLastErrorCategory(cats ...point.Category) LastErrorOption {
return func(le *LastError) {
le.Categories = cats
}
}
type Feeder interface {
Feed(name string, category point.Category, pts []*point.Point, opt ...*Option) error
FeedLastError(err string, opts ...LastErrorOption)
}