发现一个高逼格的golang“构造函数”写法

``` package main import ( "fmt" ) type options struct { a int64 b string c map[int]string } func NewOption(opt ...ServerOption) *options { r := new(options) for _, o := range opt { o(r) } return r } type ServerOption func(*options) func WriteA(s int64) ServerOption { return func(o *options) { o.a = s } } func WriteB(s string) ServerOption { return func(o *options) { o.b = s } } func WriteC(s map[int]string) ServerOption { return func(o *options) { o.c = s } } func main() { opt1 := WriteA(int64(1)) opt2 := WriteB("test") opt3 := WriteC(make(map[int]string,0)) op := NewOption(opt1, opt2, opt3) fmt.Println(op.a, op.b, op.c) } ``` 如上,最近看grpc的源码,发现了里面一种高逼格的构造函数的写法,表示震惊,学到了新姿势。
已邀请:
这样那?

```go
package main

import (
"fmt"
)

type options struct {
a int64
b string
c map[int]string
}

func (o *options) writeA(a int64) *options {
o.a = a
return o
}
func (o *options) writeB(b string) *options {
o.b = b
return o
}

func (o *options) writeC(c map[int]string) *options {
o.c = c
return o
}

func main() {
op := new(options)
op.writeA(int64(1)).writeB("test").writeC(make(map[int]string, 0))

fmt.Println(op.a, op.b, op.c)
}

```

h12 - https://h12.io/about

赞同来自: lwhile cholerae astaxie haoc7

這個所謂“高逼格”寫法,其實來自Rob Pike他老人家2014年寫的一篇博客:https://commandcenter.blogspot.hk/2014/01/self-referential-functions-and-design.html

學用人家發明的 Go 卻不看他老人家的博客。。。

yang11 - 初学者

赞同来自: lwhile zi marks_gui

这篇文章中也有写道,[写扩展性好的代码:函数](http://blog.jobbole.com/107442/?utm_source=blog.jobbole.com&utm_medium=relatedPosts) 这里循序渐进的写了怎样写一个扩展性好的函数,讲的挺不错的。

nilman

赞同来自: lwhile astaxie

我好几个库,都是这么写的,也是看Rob Pike 的那文章学到的。

https://github.com/fanpei91/ktable
https://github.com/fanpei91/metawire
https://github.com/fanpei91/godht
https://github.com/fanpei91/krpcwire

sonx

赞同来自: xiaoma buscoop

向晚的方法确实更优雅。但这种写法只适合在特定的场景使用,否则,我直接new一个出来在option.a=xxx这种方式更优雅。

其实就是是golang的其中一个特性,适合就好,因为用而用就不好了。

stirlingx - https://github.com/liyue201

赞同来自: lwhile

非常好,go-micro也是这种写法

touei

赞同来自: songtianyi

这种写法好理解,但是优势在哪里?

xianghanhuang

赞同来自: haoxiong

灵活性带来的是性能降低,成员变量越多越明显,用的时候还是要根据实际情况的。能直接初始化就直接初始化。

pathbox - https://pathbox.github.io/

这个高逼格是闭包吧 = = 。
我也想知道这样写有啥好处,看起来很不直观的样子
没看出来有什么优势,新增option时,调用NewOption者依然要修改调用的地方,加入新的option。
缺点反倒有,引入了 ServerOption ,间接隔离了数据和修改数据的方法。
至少在绝大多数场景下,我认为 @向晚 提供的方法更好。
之前每日新闻里有推荐.
很多库都是这么写的.
@向晚 的方法我看到zap也用到了这种方法
前面提到的那个。。。不就是最简单的builder模式吗= =。

Mrwxj - 图样图森破

这就是一种编程模式吧 和链式编程一样的
向晚提供的更像go代码,从go的焦点更容易理解,楼主的方式从java/js的角度更容易理解
就是常规写法,LZ孤陋寡闻了
楼主的写法好处是无论options内部结构发生什么变化,NewOption函数都不用修改。向晚的方法并不是构造函数,如果options在其他包里就不能用了
感谢 楼主分享

leyafo - http://www.leyafo.com/

可不可以把 writeA, writeB, writeC 继续用代码生成呢?
elasticSearch 包也是这样写的
一个构造参数太多 这样写比较爽 不需要在意参数位置
什么时候写程序的, 也标题党了?.................


就是 golang 的基本写法, 什么时候变成高级了....................
golang 说实话, 在开发语言本身上, 即没有语法糖( 也有, 很少语法糖), 也没有高级写法, 更没有黑魔法, 可能说是即简单又无趣. golang 用时间长了, 时间精力都放在业务/算法上, 加上 golang 的 pprof 这类工具链完整而基本算是足够用, go写的程序在测试/调优上也挺无趣: 花时间好好监测各指标前后变化, 找到优化点, 是可以预期的..........也算是无趣的一点.
それは面白い投稿です。 私はあなたのブログに戻ってきます。 [basketball games](http://basketballgames.io/ "basketball games")

要回复问题请先登录注册