为什么我觉得 GO 有些语法很奇怪?

2022-05-29 10:27:10 +08:00
 Lighthughjiajin

我是初学者,刚开始学习 Go ,遇到了下面这些问题…有没大佬给我讲讲 Go 为什么这么设计…

1 、为什么导入包的时候,需要使用双引号引起来,使用的时候确直接是包名(像 Java, Python 导入时不需要双引号,使用时也不需要,可以明确的知道导入对象后,给一个变量指向它)

2 、为什么 package main 的时候又不需要双引号引起来了?

3 、为什么定义变量的方式有这么多?

4 、为什么在函数体外又不能使用 := 定义变量?

5 、为什么使用 var 或者 := 定义的变量不使用,无法通过编译?但是 const 定义的变量却可以?

8191 次点击
所在节点    Go 编程语言
59 条回复
StevenRCE0
2022-05-29 12:37:46 +08:00
@cmdOptionKana 可以可以,体会到了语言设计哲学思想
bruce0
2022-05-29 12:45:55 +08:00
引用我高中英语老师的一句话, 语法没有为什么 就是这样规定的. 苹果为什么叫 Apple 香蕉为什么叫 banana 没有为什么 就是这样规定的
sciel
2022-05-29 12:48:11 +08:00
周经贴,下次换个新奇的角度~
gogorush
2022-05-29 12:49:21 +08:00
https://go.dev/ref/spec
大概看一遍 不懂就多问 也可以先自己查下为啥 手动狗头
ClericPy
2022-05-29 13:10:36 +08:00
虽然是周经, 但回帖似乎分成了两派: 一派觉得楼主是吐槽, 完全没有解答的欲望; 另一派认认真真回答楼主的疑问, 不管问的问题多常见

后者是我七年前刚来 V2 时候的熟悉的味道, 前者是我二十年前逛贴吧的味道... 至少我觉得楼主问的问题和那几个回答都挺有价值的
Trim21
2022-05-29 13:14:53 +08:00
package 和 import 这个问题,因为 import 的时候是一个 git repo ,所以可能有奇怪的字符吧…
但是包名不能有奇怪的东西比如分割域名的.,所以不需要双引号也不会有奇怪的语法出现
Trim21
2022-05-29 13:18:22 +08:00
@Trim21 所以我猜测一下,是方便那群人写语法解析器
yolee599
2022-05-29 13:23:29 +08:00
我看到 go 写的 hello world 的时候就觉得这个语言的语法比较随意,如果之前是写 java ,C# 的大概率会不适应,如果之前是写 Python ,JavaScript 那就不觉得奇怪了
sciel
2022-05-29 13:31:44 +08:00
@ClericPy 说得很对,下次注意了,对提问者没有什么帮助的信息还是不要回好了。抱歉~

我也是用 golang 的,等你用久了就可以体会,其实 golang 的语法还是很不错的。

以一个获取接口数据的方法为例,返回状态为 0 和 1 时的数据。 用 d,err:= 方便接收又不用加新的类型定义,switch 的 case 可以同时 case 多个值。整体逻辑写起来可以很清爽。 而且想要测试方法,创建一个 TestFetchData 方法就可以。

```
func fetchData2(ctx context.Context, url string) (*gjson.Json, error) {
d, err := gclient.New().Timeout(time.Second*3).Retry(5, time.Second*3).Get(ctx, url) // 重试 5 次,每次间隔 3 秒
if err != nil {
glog.Error(ctx, err)
return nil, err
}
json, err := gjson.DecodeToJson(d.ReadAll())
if err != nil {
return nil, err
}
switch json.Get("code").Int() {
case 0, 1:
return json.GetJson("data"), nil
default:
return nil, errors.New("获取数据失败,请稍后重试")
}
}
llbbzh
2022-05-29 13:43:04 +08:00
提供一条思路:

1/2. 因为导入包的时候,包的路径比较复杂,有点、斜杠、短杠等各种特殊符号;而定义包名的时候,包名一定是一个标识符。如果语法上设计成包的路径用引号包裹起来的话,编译器中的 tokenizer 和 parser 就很好写。如果不是的话,就要为 import 包设计一套特殊的处理逻辑,很麻烦
Jooooooooo
2022-05-29 14:02:19 +08:00
我感觉楼主问的几个问题确实是好问题.

有一个我能解答, 为什么这么多种定义变量的方法.

这都是语法糖吧, 如果像 java 都写 Person p = new Person(), 总是感觉很冗余. 右边明明和左边重复了.
lysS
2022-05-29 14:09:54 +08:00
都是设计而已,这种东西纯看设计者的经验
假如只有 var ,v2 又会多一个贴,标题是:都 21 世纪了,Go 作为高级语言为什么没有自动类型推导?
koebehshian
2022-05-29 14:10:19 +08:00
对于第 1 个问题,我搜了一下: https://stackoverflow.com/questions/36666112/why-go-requires-double-quoted-import-declaration
就是因为是路径,不是包名,路径中可能需要转义。
这样第 2 个问题,也很好解释了,就是只是包名,不是路径,就不需要引号
Suddoo
2022-05-29 14:25:34 +08:00
问就是大道至简
ClericPy
2022-05-29 14:36:42 +08:00
@sciel 没有针对你哈...

就是感觉楼主新手上路时候, 怀有好奇心探索精神对一些设计想探究一下原因, 实际上并不是上面很多人嘴里的吐槽语法或者和其他语言比孰强孰弱. golang 作为一个较新的语言, 反传统语言的一些设计肯定是有原因的, 探讨一下是非常有好处的. 至于我也没说什么和问题有关的, 实在是已经被人回答的挺好了(有几个问题也解开了我的疑惑)
a90120411
2022-05-29 14:38:07 +08:00
结论:Go 从语法层面本身就谈不上优雅。

以下均为个人主观观点,能力有限,如有错误,请大家不吝斧正:

#1 & #2:package 定义的是 标识符(有名称字符限制,参考 3 ),import 定义的是包所在路径。import 加了引号容易解析(路径中可能包含路径分隔符,空格、点符号等),此外保留了一些灵活性,联想一些代码生成器之类的吧。
但其实 import 的引号是完全可以去除或者做成可选的,即使它包含特殊符号的情况下,并不是很难的解析。

参考:
[1] package declaration without quotes while import package use quotes ?
https://github.com/golang/go/issues/32185
[2] https://stackoverflow.com/questions/36666112/why-go-requires-double-quoted-import-declaration
[3] https://go.dev/ref/spec#Qualified_identifiers

---------

#3:确实挺多,用起来很灵活,有些设计确实很实用,有些又感觉是开倒车。
没有代码规范的约束,很容易产生阅读理解困难,我不是很喜欢这种类型后置的语法。

参考:
[1] 我们真的需要 var 吗?
https://groups.google.com/g/golang-nuts/c/qTZemuGDV6o/m/IyCwXPJsUFIJ
[2] 对 Go 语言的综合评价 - 王垠
https://www.yinwang.org/blog-cn/2014/04/18/golang

---------

#4:引用 Ian Lance Taylor 的回答。他是 Google 的员工,Go 的开发者。
在全局作用域,所有的声明都要使用关键字,目的是方便解析器解析(不是很有说服力)。

参考:
[1] https://groups.google.com/g/golang-nuts/c/qTZemuGDV6o/m/IyCwXPJsUFIJ
[2] https://groups.google.com/g/golang-nuts/c/OqYL9lgsPQ4/m/udp0nPHPZTgJ

---------

#5:是一种刻板且体验极差的设计,但官方跟你说(参考 1 )这是为了你好。

参考:
[1] https://go.dev/doc/faq#unused_variables_and_imports
[2] https://stackoverflow.com/questions/21743841/how-to-avoid-annoying-error-declared-and-not-used
acehowxx
2022-05-29 16:40:21 +08:00
对于 go .除了 if err!=nil 以外,对其他方面都比较满意。未来的错误处理如果用?向上抛的话可以省掉大量的 err 判断。
Zwying
2022-05-29 19:57:12 +08:00
倘若你一开始学习的就是 Go ,你或许会对 java 发出一样的感叹,习惯而已
alsas
2022-05-29 20:11:53 +08:00
问就是特立独行 问就是工程设计
c8iter
2022-05-29 20:26:47 +08:00
多线程中断管理,真是酸爽

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/855980

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX