Go 语言入门指南:基础语法和常用特性解析1 | 青训营

95 阅读6分钟

此篇文章是我参与 #青训营笔记创作活动 的第9篇笔记

主要是简单记录一下自己在学习Go语言基础语法中的变量部分时遇到的一些小要点,

只是个人的一个学习记录,水平不高还望大佬们包容。

0x01 变量的声明

声明变量的一般形式是使用 var 关键字:

var name type
  • var 是声明变量的关键字,name 是变量名,type 是变量的类型
    • var 变量名 变量类型
    • 行尾无须分号
  • 声明变量时将变量的类型放在变量的名称
    • 避免像C语言中那样含糊不清的声明形式,例如:int* a, b; 。其中 a 是 int 指针,而 b 是 int 类型的变量
    • 如果你想要这两个变量都是指针,则需要将它们分开书写
  • 变量的基本类型
    • bool
    • string
    • int、int8、int16、int32、int64
    • uint、uint8、uint16、uint32、uint64、uintptr
    • byte
      • uint8 的别名
    • rune
      • int32 的别名 代表一个 Unicode 码
    • float32、float64
    • complex64、complex128(复数)
      • complex64中实部和虚部是32位的,在complex128中实部和虚部是64位的

批量格式

  • 可以用括号来进行批量声明变量

  • var (
        a int
        b string
        c []float32
        d func() bool
        e struct {
            x int
        }
    )
    

简短格式

  • 名字 := 表达式

  • i, j := 0, 1
    
  • 需要注意的是,简短模式(short variable declaration)有以下限制:

    • 定义变量,同时显式初始化
    • 不能提供数据类型
    • 只能用在函数内部


0x02 变量的初始化

当一个变量被声明之后,系统自动赋予它该类型的零值

  • 整型和浮点型变量的默认值为 0 和 0.0
  • 字符串变量的默认值为空字符串
  • 布尔型变量默认为 bool
  • 切片、函数、指针变量的默认为 nil

所有的内存在 Go 中都是经过初始化的

当然,我们依然可以在变量声明时赋予变量一个初始值。


回顾C语言:

在C语言中,变量在声明时,并不会对变量对应内存区域进行清理操作。此时,变量值可能是完全不可预期的结果。开发者需要习惯在使用C语言进行声明时要初始化操作,稍有不慎,就会造成不可预知的后果。

在网络上只有程序员才能看懂的“烫烫烫”和“屯屯屯”的梗,就来源于 C/C++ 中变量默认不初始化。

微软的 VC 编译器会将未初始化的栈空间以 16 进制的 0xCC 填充,而未初始化的堆空间使用 0xCD 填充,而 0xCCCC 和 0xCDCD 在中文的 GB2312 编码中刚好对应“烫”和“屯”字。

因此,如果一个字符串没有结束符\0,直接输出的内存数据转换为字符串就刚好对应“烫烫烫”和“屯屯屯”。


初始化的标准格式

var 变量名 类型 = 表达式
  • 在标准格式的基础上,将 int 省略后,编译器会尝试根据等号右边的表达式推导变量的类型
  • 等号右边的部分在编译原理里被称做右值(rvalue)

初始化的简短格式

变量名 := 表达式
  • 编译器会自动根据右值类型推断出左值的对应类型

  • 由于使用了:=,而不是赋值的=,因此推导声明写法的左值变量必须是没有定义过的变量

    • 若定义过,将会发生编译错误
  • 在多个短变量声明和赋值中,至少有一个新声明的变量出现在左值中,即便其他变量名可能是重复声明的,编译器也不会报错

    • a, b := 1, 2
      a, c := 1, 3
      

变量交换

  • 中间变量交换法
    • temp = a
    • a = b
    • b = temp
  • 加减交换法
    • a = a + b
    • b = a - b
    • a = a - b
    • 注意:
      • 不能交换非数字类型的变量
      • 对于浮点类型的变量可能会出现问题
      • 加法过程中可能会出现超出上限的问题
  • 异或交换法
    • a = a ^ b
    • b= a ^ b
    • a = a ^ b
    • 注意:
      • 只能用于交换可以进行异或运算的数据类型
      • 如果 a , b 指向同一个内存地址,则异或交换法失效
  • “多重赋值” 变量交换法
    • b, a = a, b
    • 利用 Go 语言的“多重赋值”特性(其实python也可以用这个方法来交换变量)
    • 多重赋值时,变量的左值和右值按从左到右的顺序赋值


0x03 匿名变量

在编码过程中,可能会遇到没有名称的变量、类型或方法。虽然这不是必须的,但有时候这样做可以极大地增强代码的灵活性,这些变量被统称为匿名变量。

在 Lua 等编程语言里,匿名变量也被叫做哑元变量

  • 匿名变量的特点是一个下画线_

    • _本身就是一个特殊的标识符,被称为空白标识符
  • 它可以像其他标识符那样用于变量的声明或赋值

    • 任何类型都可以赋值
  • 不可后续使用

    • 任何赋给这个标识符的值都将被抛弃
    • 因此这些值不能在后续的代码中使用
    • 也不可以使用这个标识符作为变量对其它变量进行赋值或运算。
  • 使用匿名变量时,只需要在变量声明的地方使用下画线替换即可

    • _ , a:= 1, 2
      
  • 不占用内存空间

    • 匿名变量不占用内存空间,不会分配内存
  • 可多次声明

    • 匿名变量与匿名变量之间也不会因为多次声明而无法使用


0x04 作用域

根据变量定义位置的不同,可以分为以下三个类型:

  • 局部变量
    • 函数内定义的变量
    • 作用域只在函数体内,函数的参数和返回值变量都属于局部变量
    • 函数调用结束后局部变量就会被销毁
  • 全局变量
    • 函数外定义的变量
    • 全局变量只需要在一个源文件中定义,就可以在所有源文件中使用
    • 不包含这个全局变量的源文件需要使用“import”关键字引入全局变量所在的源文件之后才能使用这个全局变量
  • 形式参数
    • 函数定义中的变量
      • 在定义函数时函数名后面括号中的变量叫做形式参数(简称形参)
    • 形式参数只在函数调用时才会生效,函数调用结束后就会被销毁,在函数未被调用时,函数的形参并不占用实际的存储单元,也没有实际值。


附录

本文参考链接及推荐阅读:

Go 语言基础语法 | 菜鸟教程 (runoob.com)

Go语言基本语法 (biancheng.net)