10|变量声明:静态语言有别于动态语言的重要特征
10|变量声明:静态语言有别于动态语言的重要特征
讲述:Tony Bai
时长17:04大小15.60M
Go 语言的变量声明方法
包级变量的声明形式
局部变量的声明形式
小结
思考题
赞 56
提建议
精选留言(38)
- 珅珅君2021-11-03https://blog.go-zh.org/gos-declaration-syntax 其实官方有给出解释,原因简单来说就是和C相比,在当参数是指针的复杂情况下,这种声明格式会相对好理解一点,链接里面有详细解释
作者回复: 正解。
共 3 条评论26 - jc9090kkk2021-11-03我认为类型放在变量名的后面是为了提高代码可读性的,我个人认为golang的设计者在设计go语言的时候大概率参考了c语言的语法,针对存在大量变量需要声明的场景下,go的变量类型放在变量名的后面可读性会高很多,不容易引起类型定义的混乱。 比如: c: int (*fp)(int a, int b); int (*fp)(int (*ff)(int x, int y), int b) go: f func(func(int,int) int, int) int f func(func(int,int) int, int) func(int, int) int 相比之下:go的清晰易懂!而c的层层嵌套,难以直接看出是什么类型的指针 另外的一点我认为也是大多编程语言开发者的习惯,语法定义后紧接着就是变量名应该是很多编程者的开发习惯,如果var后面跟着int类型这样的语法会让人很别扭,至少对我来讲是这样。展开
作者回复: ✅。答案非常细致。刚开始学go时,也不适应,后来适应后,就像你说的,在一些复杂函数/方法的声明中,类型在后面的方式更容易理解。
21 - witt2021-11-03为了不一样而不一样?必要的写在最前面,不必要的可以省略的写在后面?8
- hhzzer2021-11-03想问一下老师,为啥go产生了这么多种变量声明方式?依照一个问题只用一种方法解决的原则,如果你重新设计,会选择保留哪一种申明方式呢?
作者回复: 1. 保留这么多变量声明方式的原因,Go语言设计者们并未在公开场合说明过。这个我也无不能不负责任的揣测^_^。 2. rob pike只是说过,如果有机会从头设计go,他不会再提供这么多变量声明方式了。但没说要保留哪一种。如果是我设计,我可能会保留var a int以及短变量声明。
8 - 高雪斌2021-11-03就是既想要静态语言的严格,又想取动态语言的灵活的折中方案。
作者回复: 选Go就对了:)
5 - Leo2021-12-01老师最后还贴图了 太感动了4
- aoe2021-11-03短短的几行代码没看懂……共 1 条评论4
- 修文2021-11-10就近原则介绍的例子中提到,ErrNoCookie 只被用在了 Cookie 方法中。有一个疑问是,为什么 ErrNoCookie 不定义在方法中,而是定义在方法外呢?
作者回复: 后面会降到,go的错误处理是基于值比较的。之所以将ErrNoCookie放在包级而不是函数/方法内部,是因为需要将ErrNoCookie暴露给包的使用者。这样包的使用者才能通过ErrNoCookie与方法返回的错误值进行比较以判断是否是这个错误。
共 3 条评论3 - 陈东2021-11-03从源头开始讲,这一讲很好,知所以然。2
- 大大~喜羊羊2021-11-03这么多声明语法确实有选择恐惧症了,就是不知道随心所欲地去声明变量后面会不会给自己挖坑2
- AlexWillBeGood2021-11-03老师好,请问“静态语言明确声明类型”会在编译阶段或运行阶段提高效率吗?
作者回复: 我觉得与效率无关。静态语言的类型声明是静态语言的机制所要求的。静态语言原本运行效率就是要比动态语言要高的,因为它已经编译为机器码了,无需开销较大的解释过程就可以运行了。
2 - Ayasan2022-08-16 来自北京最后那个图感觉不够严谨呀,包级变量的a应该是大写才对吧。
作者回复: 只有导出的包级变量才需要大写。这些只是偏重于讲解Go变量的声明形式。
1 - pyhhou2022-02-28老师,最后那张图里的例子是不是括号打错了,比如 a := (int32)17 是不是应该是 a := int32(17) ? (类型说明符)表达式 确实是某些静态语言(比如 C,Java)里的显示类型转换,go 里面是两种形式都支持吗?
作者回复: 好眼力👍!图片中的语法错了。go只支持一种:int32(17)。我让编辑老师修改一下。
1 - Paradise2022-02-09类型是放在变量名的后面是为了让 TypeScript 开发者入坑go 嘿嘿嘿
作者回复: 不搞前端,ts不熟悉,ts也是将类型放在变量名后面?
共 2 条评论1 - 步比天下2021-12-30最后的图真好~
作者回复: 👍
1 - 陈衎2021-12-12真的讲的好详细。没想到go的变量还能细分出这么多内容。从接触就知道使用块声明和短变量声明,尤其是短变量声明这种语法糖认为就是作者所推荐和提倡统一的,看完本课后真的受益良多。
作者回复: 👍
1 - Calvin2021-11-07学习总结笔记: 1、静态类型语言编译器必须明确知道一个变量的边界,一般通过“变量声明”,由变量的类型属性显式地告知; 2、var a int = 10,Go 声明变量的 4 个部分:var 表明这是一个“变量”,a 是“变量名”,int 是变量的类型,10 是变量的初始化值; 1) var a int // 声明变量 a,不指定初始化值(编译器会赋予其类型零值,int 默认零值是 0) 2) var ( a int = 128 s string = "hello" ) // 变量声明块 3) var a, b, c int = 5, 6, 7 // 在一行变量声明中同时声明多个变量(相同类型) 4) var a, b, c = 3, 'b', "ccc" // 在一行变量声明中同时声明多个变量(不同类型) 5) var ( a, b, c int = 1, 2, 3 d, e, f rune = 'D', 'E', 'F' ) // 变量声明块,在一行变量声明中同时声明多个变量 6) var a = 123 // 编译器根据右侧变量初始化值自动推导出变量的类型为 int(整型值的默认类型) 7) var b = int32(123) // 不接受默认推导类型 int,显式地为变量指定类型为 int32 8) c := 123 // 短变量声明(省掉 var 及类型信息,使用专用的“:=”) 9) d, e, f := 123, 'A', "bcd" // 短变量声明,在一行变量声明中同时声明多个变量 3、Go 变量可以分为两类: 1) 包级变量:包级别可见的变量,如果是导出变量(大写字母开头的),它也可被视为“全局变量”; 2) 局部变量:仅在函数或方法体内可见。 4、包级变量 - 只能使用带有 var 关键字的变量声明形式,不能使用短变量声明形式,但在形式细节上可以有一定灵活度: 1) 声明并同时显式初始化:var EOF = errors.New("EOF"),注意“声明一致性”原则,即如既有 var a = 123 这种使用默认类型的形式,又有 var b int32 = 321 或 var b = int32(321) 这种显式指定类型的形式,Go 更推荐使用后者; 2) 声明但延迟初始化:var a int32。 5、提升代码可读性: 1) 声明聚类:将同一类的变量声明放在一个 var 变量声明块中,不同类的声明放在不同的声明块中,如: var ( netGo bool netCgo bool ) // 声明但延迟初始化 var ( aLongTimeAgo = time.Unix(1, 0) noDeadline = time.Time{} noCancel = (chan struct{})(nil) ) // 声明并同时显式初始化 2) 就近原则:尽可能在靠近第一次使用变量的位置声明这个变量,实际上也是对变量的作用域最小化的一种实现手段,如果一个包级变量在包内部被多处使用,则还是放在源文件头部比较适合。 6、局部变量 - 和包级变量相比,多了一种短变量声明形式,这是局部变量特有的一种变量声明形式,也是局部变量采用最多的一种声明形式: 1) 对于延迟初始化的局部变量声明,我们采用通用的变量声明形式:var err error 2) 对于声明且显式初始化的局部变量,建议使用短变量声明形式:a := 123,f := float32(3.14) 3) 尽量在分支控制时使用短变量声明形式,这种融合的使用方式也体现出“就近”原则,让变量的作用域最小化; 4) 如果在声明局部变量时遇到了适合聚类的应用场景,应该毫不犹豫地使用 var 声明块来声明多于一个的局部变量: func (r *Resolver) resolveAddrList(ctx context.Context, op, network, addr string, hint Addr) (addrList, error) { ... ... var ( tcp *TCPAddr udp *UDPAddr ip *IPAddr wildcard bool ) ... ... } 7、Go 语言变量声明中,类型是放在变量名的后面的,这样做的好处:https://go.dev/blog/declaration-syntax展开
作者回复: 赞👍
共 2 条评论2 - 进化菌2021-11-04go的变量声明,方式还是挺灵活的。 把类型放在变量名后面,大概是更方便清晰的说明吧,毕竟前面已经有var关键字了~1
- liaomars2021-11-03变量名放在前面应该是考虑代码的可读性才这样设计的吧
作者回复: 大约是如此。可以看看官方解释:https://go.dev/blog/declaration-syntax
2 - 罗杰2021-11-03C 和 C++ 都是类型在前,变量名在后,记得非常清楚 CCMouse 老师在视频课上提到这才是正确的方法,但到现在其实我还没太明白原因。不过在 Rust 中采用了和 Go 相同的方式。所以希望老师解答一下原因
作者回复: 其实官方早有正解,https://go.dev/blog/declaration-syntax 。我个人以前是C程序员,在读懂那些复杂函数的原型时,颇为费力。换做go之后,再未被这类问题困扰过:)
1