• 珅珅君
    2021-11-03
    https://blog.go-zh.org/gos-declaration-syntax 其实官方有给出解释,原因简单来说就是和C相比,在当参数是指针的复杂情况下,这种声明格式会相对好理解一点,链接里面有详细解释

    作者回复: 正解。

    共 3 条评论
    33
  • jc9090kkk
    2021-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时,也不适应,后来适应后,就像你说的,在一些复杂函数/方法的声明中,类型在后面的方式更容易理解。

    
    25
  • hhzzer
    2021-11-03
    想问一下老师,为啥go产生了这么多种变量声明方式?依照一个问题只用一种方法解决的原则,如果你重新设计,会选择保留哪一种申明方式呢?

    作者回复: 1. 保留这么多变量声明方式的原因,Go语言设计者们并未在公开场合说明过。这个我也无不能不负责任的揣测^_^。 2. rob pike只是说过,如果有机会从头设计go,他不会再提供这么多变量声明方式了。但没说要保留哪一种。如果是我设计,我可能会保留var a int以及短变量声明。

    
    9
  • 高雪斌
    2021-11-03
    就是既想要静态语言的严格,又想取动态语言的灵活的折中方案。

    作者回复: 选Go就对了:)

    
    6
  • 修文
    2021-11-10
    就近原则介绍的例子中提到,ErrNoCookie 只被用在了 Cookie 方法中。有一个疑问是,为什么 ErrNoCookie 不定义在方法中,而是定义在方法外呢?

    作者回复: 后面会降到,go的错误处理是基于值比较的。之所以将ErrNoCookie放在包级而不是函数/方法内部,是因为需要将ErrNoCookie暴露给包的使用者。这样包的使用者才能通过ErrNoCookie与方法返回的错误值进行比较以判断是否是这个错误。

    共 3 条评论
    5
  • Calvin
    2021-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 条评论
    4
  • CLMOOK🐾
    2022-09-27 来自北京
    老师好,按我的理解,显式指定变量类型,在编译器的执行效率上,是比不指定类型,或进行显式转换类型要高的,因为省略了编译器根据值去判断类型,或做类型转换的开销,但由于go程序都是编译后运行二进制文件,所以编译过程的开销就没那么重要或者说可以忽略,然后可以更多的考虑使用便利性和代码可读性。

    作者回复: 👍

    
    3
  • liaomars
    2021-11-03
    变量名放在前面应该是考虑代码的可读性才这样设计的吧

    作者回复: 大约是如此。可以看看官方解释:https://go.dev/blog/declaration-syntax

    
    3
  • 罗杰
    2021-11-03
    C 和 C++ 都是类型在前,变量名在后,记得非常清楚 CCMouse 老师在视频课上提到这才是正确的方法,但到现在其实我还没太明白原因。不过在 Rust 中采用了和 Go 相同的方式。所以希望老师解答一下原因

    作者回复: 其实官方早有正解,https://go.dev/blog/declaration-syntax 。我个人以前是C程序员,在读懂那些复杂函数的原型时,颇为费力。换做go之后,再未被这类问题困扰过:)

    
    3
  • 福杯满溢
    2022-11-13 来自北京
    老师请教下,对于省略类型的变量声明,如var a = 12342342342434424,那么这个a变量的默认类型就不是int类型了吧?

    作者回复: int在64位平台上就是64位的。 func main() { var a = 12342342342434424 fmt.Printf("%T, %d\n", a, a) // int, 12342342342434424 } 类型还是int

    
    2