不一样的go语言-玩转语法之一
程序员文章站
2022-12-22 15:10:49
这段时间为俗事所累,疲以应付,落下了不少想法,错过了更新的日子。这个专题开始之际,已经准备了不下十几个主题,而在写作的过程中,又有新想法与主题涌现出来。未来预计想写写的内容主要包括: 1. 玩转语法系列 2. Context的来龙去脉 3. 函数、闭包与范畴论的关系 4. 线 ......
这段时间为俗事所累,疲以应付,落下了不少想法,错过了更新的日子。这个专题开始之际,已经准备了不下十几个主题,而在写作的过程中,又有新想法与主题涌现出来。未来预计想写写的内容主要包括:
- 玩转语法系列
- context的来龙去脉
- 函数、闭包与范畴论的关系
- 线程与协程之争
- 通道的那些事
今天的玩转语法系列,先起个头,调子稍微低一点,主要想与大家分享一下go语言在实践中的优美之处。用不同的语言来解决相同的问题,最能直观感受语言的魅力。
先来看看一版java代码的例子(这里没有贬低java的意思,仅仅是举个例子,java是一门很实用的语言):
public class tea { //名称 private string name; //奶 public boolean milk; //珍珠 public boolean pearl; //冰 public boolean ice; public string tostring() { return name.concat(", ") .concat("milk: ") .concat(string.valueof(milk)) .concat(", pearl: ") .concat(string.valueof(pearl)) .concat(", ice: ") .concat(string.valueof(ice)); } } public class heyteamaker { public tea make(string name, boolean milk, boolean pearl, boolean ice) { tea tea = new tea(); tea.name = name; tea.milk = milk; tea.pearl = pearl; tea.ice = ice; return tea; } } public static void main(string[] args) { heyteamaker maker = new heyteamaker(); tea tea = maker.make("heytea", true, true, false); system.out.println("tea: " + tea); }
上面的代码如果不加以设计,直接以这样的方式编写,那么如果需要给茶增加一个属性,比如糖,带来的修改是灾难性的,不单tea、heyteamake要修改,所有使用的地方都要修改。当然花一番心思设计一下,比如使用建造者模式包装一下。老话说,拥抱变化,java也是可以很优美的。
在这个例子中,其实茶的配料都是可选,但因为java天生没有可选参数,参数亦没有默认值,因而对于这个例子恰巧是java的弱项。而使用go就简洁多了,比如:
package main import "fmt" func main() { fmt.println(newtea("heytea", addmilk(), addpearl())) } type tea struct { name string milk bool pearl bool ice bool } func newtea(name string, option ... teaoption) *tea { tea := &tea{name: name} for _, o := range option { o(tea) } return tea } func (t *tea) string() string { return fmt.sprintf("%s, milk: %t, pearl: %t, ice: %t", t.name, t.milk, t.pearl, t.ice) } type teaoption func(t *tea); func addmilk() teaoption { return func(t *tea) { t.milk = true } } func addpearl() teaoption { return func(t *tea) { t.pearl = true } } func addice() teaoption { return func(t *tea) { t.ice = true } }
go其实也没有可选参数,参数也不允许有默认值,但因为函数与闭包的配合使用,使得go很轻松,很简洁地就解决了问题。即使要给茶增加一个属性糖,只需修改tea,并且加一个addsugar方法即可,调用的地方如果不需要糖,就不用修改。
java8已经引入了lamba与functionalinterface,其实完全依照go的实现,java也是可以写出类似的代码来。比如:
import java.util.function.function; public class tea { //名称 private string name; //奶 public boolean milk; //珍珠 public boolean pearl; //冰 public boolean ice; public string tostring() { return name.concat(", ") .concat("milk: ") .concat(string.valueof(milk)) .concat(", pearl: ") .concat(string.valueof(pearl)) .concat(", ice: ") .concat(string.valueof(ice)); } public static function<tea, void> addmilk() { return (tea t)-> { t.milk = true; return null; }; } public static function<tea, void> addpearl() { return (tea t)-> { t.pearl = true; return null; }; } public static function<tea, void> addice() { return (tea t)-> { t.ice = true; return null; }; } public static tea newtea(string name, function<tea, void> ...option) { tea tea = new tea(); tea.name = name; for (function<tea, void> item : option) { item.apply(tea); } return tea; } public static void main(string[] args) { tea tea = newtea("heytea", addice(), addmilk(), addpearl()); system.out.println("tea: " + tea); } }
功能倒是实现了,但感觉看起来仍然没有go好,一种妙不可言,只可意会不可言传的感觉。
欢迎关注个人公众号
上一篇: 为什么[]比list()更快?