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

发布于 2022-09-29 12:35:10 字数 3619 浏览 124 评论 0

早上看一篇博客 Cloud-Native Java vs Golang,然后上它的 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 最后版本)中,类型总是在变量声明之后出现

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

请止步禁区

暂无简介

文章
评论
26 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文