Golang magic code 特殊用法 (With/Option/_()/不让比较/nocmp/reset slice)

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. 即 slicemapfunc 只能和 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)
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云满笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值