zoukankan      html  css  js  c++  java
  • 不一样的go语言-玩转语法之一

      这段时间为俗事所累,疲以应付,落下了不少想法,错过了更新的日子。这个专题开始之际,已经准备了不下十几个主题,而在写作的过程中,又有新想法与主题涌现出来。未来预计想写写的内容主要包括:

    1. 玩转语法系列
    2. Context的来龙去脉
    3. 函数、闭包与范畴论的关系
    4. 线程与协程之争
    5. 通道的那些事

      今天的玩转语法系列,先起个头,调子稍微低一点,主要想与大家分享一下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好,一种妙不可言,只可意会不可言传的感觉。

    欢迎关注个人公众号

    不一样的go语言

  • 相关阅读:
    线程同步(一)
    java守护线程
    C/C++中如何获取数组的长度?
    java操作xml方式比较与详解(DOM、SAX、JDOM、DOM4J)
    按单词逆序句子(含标点)
    常见误区(一)
    java创建XML及开源DOM4J的使用
    C++学习(一)
    java读XML文件
    MiniProfiler 兼容 Entity Framework 6
  • 原文地址:https://www.cnblogs.com/laud/p/grammar_1.html
Copyright © 2011-2022 走看看