您当前的位置:首页 > 计算机 > 编程开发 > Go语言

为啥 Go 的变量类型要放在变量名后面?

时间:12-14来源:作者:点击数:

早上看一篇博客 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()
    }
}

我发现:

  1. vertx 也提供了 JSON 的支持 io.vertx.core.json.JsonArray,你看vertx也有JSON实现呢,你需要的时候,可以参考一下哦,毕竟 vertx 还是挺有名的嘛。因为它前期就搞 JSON 支持切换 fastjson 和 gson 的实现(fastjson 频繁暴露安全问题,参见 fastjson 到底做错了什么?为什么会被频繁爆出漏洞?),准备能随时在遇到安全问题时,切换实现。
  2. 然后一看这个是 kotlin 语法,竟然也是类型后置(变量类型放在变量名称后面),跟 go 语言一样。我在想,是不是比较新的语言,包括 rust,都是这么设计的啊。就像 StackOverflow 中说的这样 几乎所有现代编程语言(Go、 Rust、 Kotlin、 Swift、 Scala、 Nim,甚至 Python 最后版本)中,类型总是在变量声明之后出现(link:https://softwareengineering.stackexchange.com/a/316243)

然后我就想起,这个设计,并不单单是因为 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!」

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐