早上看一篇博客 Cloud-Native Java vs Golang(link:https://medium.com/swlh/cloud-native-java-vs-golang-2a72c0531b05),然后上它的 github仓库,顺便溜了要一眼下面的这段代码:
- package org.acme
-
- import io.vertx.core.json.JsonArray
- import io.vertx.core.json.JsonObject
- import io.vertx.mutiny.mysqlclient.MySQLPool
- import io.vertx.mutiny.sqlclient.Row
- import io.vertx.mutiny.sqlclient.RowSet
- import java.util.concurrent.CompletionStage
- import javax.inject.Inject
- import javax.ws.rs.GET
- import javax.ws.rs.Path
- import javax.ws.rs.Produces
- import javax.ws.rs.core.MediaType
-
- @Path("/fruits")
- class FruitResource {
- @field:Inject
- lateinit var client: MySQLPool
-
-
- @GET
- @Produces(MediaType.APPLICATION_JSON)
- fun listFruits(): CompletionStage<JsonArray> {
- return client.query("SELECT * FROM fruits").execute()
- .map { rows: RowSet<Row> ->
- rows.fold(JsonArray()) { array, row ->
- array.add(JsonObject()
- .put("id", row.getLong("id"))
- .put("name", row.getString("name")))
- }
- }.subscribeAsCompletionStage()
- }
- }
我发现:
然后我就想起,这个设计,并不单单是因为 style 的问题,而是有真实好处的。然后我就百度一下 why golang put type declaration afterwards,得到以下几条答案:
在形式语言理论和类型理论中,它几乎总是被写成 var: type。例如,在形式化λ演算,你会看到包含如下陈述的证明:
- x : A y : B
- -------------
- \x.y : A->B
-
我不认为这真的很重要,但我认为有两个理由: 一个是 x: a 被读作 x 是 a 型的 ,另一个是一个类型就像一个集合(例如 int 是整数的集合) ,例如 x ε a。
这些东西中的一些比你所想的现代语言还要早。
例如C语言中的 int* a, b;,只是声明了 a 是指针,而 b 并不是。或者 Go's Declaration Syntax 中提到的函数指针的声明的例子。
- int (*fp)(int a, int b);
上述声明了一个函数指针 fp,指向两个整型入参和一个整型出参的函数类型。这个还比较容易理解。好像,如果我们把第一个参数也换成函数指针,就要这么写了:
- int (*fp)(int (*ff)(int x, int y), int b);
开始看起来费劲了吧。
换成 go 版本的看看:
- f func(func(int,int) int, int) int
是不是容易看懂很多(习惯了类型后置的写法之后)。
特别是看到C语言的这种,int *(*func())();,肯定是要抓瞎了,大喊:「苍天啊,救救我吧!」然后GO说:「虽然我不是苍天,但是我能救你,欢迎使用GO!」