Go语言学习笔记-变量与作用域

2020-02-16  本文已影响0人  梁坤同学

Go 语言变量的声明

Go 语言是静态类型语言,因此变量 (variable) 是有明确类型的,编译器也会检查变量类型的正确性。

Go 语言的基本类型:

当一个变量被声明之后,系统会自动赋予它该类型的零值:int 为 0,float 为 0.0,bool 为 false,string 为空字符串,切片、函数、指针变量为 nil 等所有的内存在 Go 中都是经过初始化的。

基础数据类型.png

标准格式

变量声明以关键字 var 开头,后置变量类型,行尾无需分号。

var 变量名 变量类型

批量格式

// 只声明变量,不赋值(系统会自动赋予该类型的零值)
var a, b, c int
// 声明变量并赋值, 按顺序一一对应
var d, e, f int = 10, 20, 30

使用关键字 var 和括号,可以将一组变量定义放在一块。

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

简短格式(自动推导类型)

var 关键字外,还可使用更简短的变量定义和初始化语法。这是 Go 语言的推导声明写法,编译器会自动根据右值类型推断出左值的对应类型

变量名 := 表达式

需要注意的是,简短格式 (short variable declaration) 有以下限制:

简短格式变量声明一组变量:

i, j := 0, 1

func main() {
    x := 100
    a, s := 1, "abc"
}

简短变量声明多用于局部变量的声明和初始化。var 形式的声明语句往往用于需要显示指定变量类型的地方,或着因为变量稍后会被重新赋值而初始值无关紧要的地方。

编译器推导类型的格式

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

var 变量名 = 表达式

Go 语言的多重赋值

以往我们进行变量交换的时候,传统的方式是需要一个中间变量进行变量的临时保存。又或者为了不占用内存,使用其他的一些算法来避免使中间变量,这样的算法很多,但是都有一定的数值范围和类型要求。

var a int = 100
var b int =200

a = a * b
b = a / b
a = a / b
fmt.Println(a, b)   // 200 100

在 Go 语言中,使用 Go 的 "多重赋值" 特性,可以轻松完成变量交换的任务:

var a int = 100
var b int = 200
b, a = a, b
fmt.Println(a, b)   // 200 100

多重赋值时,变量的左值和右值按从左到右的顺序赋值。

Go 语言的匿名变量

匿名变量不占用内存空间,不会分配内存。
匿名变量与匿名变量之间也不会因为多次声明而无法使用。

匿名变量的特点是一个下画线 "", "" 本身就是一个特殊的标识符,被称为空白标识符。它可以像其他标识符那样用于变量的声明或赋值(任何类型都可以赋值给它),但任何赋给这个标识符的值都会被抛弃,因为这些值不能在后续的代码中使用,也不可以使用这个标识符作为变量对其他变量进行赋值或运算。使用匿名变量时,只需要在变量声明的地方使用下画线替换即可。

func GetData() (int, int) {
    return 100, 200
}
func main() {
    a, _ = GetData()    // 只取第一个值
    _, b = GetData()    // 只取第二个值
    fmt.Println(a, b)   // 100 200
}

Go 语言变量的作用域(与 js 类似)

作用域:一个变量(常量、类型或函数)在程序中的作用范围。

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

局部变量

在函数体内声明的变量称之为局部变量,它们的作用域只在函数体内,函数的参数和返回值变量都属于局部变量。

函数变量不是一直存在的,它只在定义它的函数被调用后存在,函数调用结束后这个局部变量会被销毁。

全局变量

在函数体外声明的变量称之为全局变量,全局变量只需要在一个源文件中定义,就可以在所有源文件中使用,当然,不包含这个全局变量的源文件需要使用 "import" 关键字引入全局变量所在的源文件之后才能使用这个全局变量。

全局变量声明必须以 var 关键字开头,如果想要在外部包中使用全局变量的首字母必须大写。

Go 语言程序中全局变量与局部变量名称也可以相同,但是函数体内的局部变量会被优先考虑(类似于 js 的作用域链)。

形式参数

在定义函数时函数名后面括号中的变量叫做形式参数(简称形参)。形参只在函数调用时才会生效,函数调用结束后就会被销毁,在函数未被调用时,函数的形参并不占用实际的存储单元,也没有实际值。

形参会作为函数的局部变量来使用。

package main

import "fmt"

// 全局变量 a
var a int = 13

func main() {
    fmt.Printf("全局变量 a = %d\n", a)

    // 声明局部变量 a 和 b 并赋值
    var a, b int = 3, 4

    fmt.Printf("main() 函数中 a = %d\n", a)
    fmt.Printf("main() 函数中 b = %d\n", b)
    // 声明局部变量 c 并计算 a 和 b 的和
    c := sum(a, b)
    fmt.Printf("main() 函数中 c = %d\n", c)
}

// a 和 b 为形参
func sum(a, b int) int {
    fmt.Printf("sum() 函数中 a = %d\n", a)
    fmt.Printf("sum() 函数中 b = %d\n", b)

    num := a + b
    return num
}

Go 语言整型(整数类型)

Go 语言的数值类型分为以下几种:整数、浮点数、复数,其中每一种都包含了不同大小的数值类型,例如有符号整数包含 int8、int16、int32、int64 等,每种数值类型都决定了对应的大小范围和是否支持正负符号。

Go 语言同时提供了有符号和无符号的整数,类型其中包括 int8、int16、int32、int64 四种大小截然不同的有符号整数类型,分别对应8、16、32、64 bit(二进制位) 大小的有符号整数,于此对应的是 uint8、uint16、uint32、uint64 四种无符号整数类型。

此外还有两种整数类型 int 和 uint,它们分别对应特定 CPU 平台得字长(机器字大小),其中 int 表示有符号整数,应用最为广泛,uint 表示无符号整数。实际开发中由于编译器和计算机硬件的不同,int 和 uint 所能表示的整数大小会在 32bit 或 64bit 之间变化。

大多数情况下,我们只需要 int 一种整型即可,它可以用于循环计数器(for 循环中控制循环此的变量)、数组和切片的索引,以及任何通用目的的整型运算符,通常 int 类型的处理速度也是最快的

Go 语言中有符号整数采用 2 的补码形式表示,也就是最高 bit 位用来表示符号位,一个 n-bit 的有符号数的取值范围是从 -2^(n-1)2^(n-1) - 1。无符号整数的所有 bit 位都用于表示非负数,取值范围是 02^n - 1。例如,int8 类型整数的取值范围是从 -128127,而 uint8 类型整数的取值范围是从 0255

Go 语言的浮点类型(小数类型)

Go 语言提供了两种精度的浮点数 float32float64。一个 float32 类型的浮点数可以提供大约 6 个十进制数的精度,而 float64 则可以提供约 15 个十进制数的精度,通常应优先使用 float64 类型,因为 float32 类型的累计计算误差很容易扩散,并且 float32 能精确表示的正整数并不是很大。

浮点数取值范围的极限值可以在 math 包中找到:

Go 语言的复数

在计算机中,复数是由两个浮点数表示的,其中一个表示实部(real),一个表示虚部(imag)。

Go 语言中的复数的类型有两种,分别是 complex128(64位实数和虚数)和 complex64(32位实数和虚数),其中 complex128 为复数的默认类型

复数的值由三部分组成 RE + IMi, 其中 RE 是实数部分,IM是虚数部分,RE 和 IM 均为 float 类型,而最后的 i 是虚数单位。

声明复数的语法格式:

var name complex128 = complex(x. y)

x, y 分别表示构成该复数的两个 float64 类型的数值,x 为实部,y 为虚部。

也可用简短格式:

name := complex(x, y)

可以通过 Go 语言的内置函数 real(z) 来获取该复数的实部,也就是 x;通过 imag(z) 获得该复数的虚部,也就是 y。

复数运算法则

复数也可以用 ==!= 进行相等比较,只有两个复数的实部和虚部都相等的是哦胡它们才是相等的。

上一篇下一篇

猜你喜欢

热点阅读