早上看一篇博客 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!」

