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

Go 语言变量的声明

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

Go 语言的基本类型:

  • bool
  • string
  • int、int8、int16、int32、int64
  • uint、uint8、uint16、uint32、uint64、uintptr
  • byte // uint8 的别名
  • rune // int32 的别名,代表一个 Unicode 码
  • float32、float64
  • complex64、complex128

当一个变量被声明之后,系统会自动赋予它该类型的零值: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 包中找到:

  • 常量 math.MaxFloat32 表示 float32 能取到的最大数值,大约是 3.4e38
  • 常量 math.MaxFloat64 表示 float64 能取到的最大数值,大约是 1.8e308
  • float32float64 能表示的最小值分别为 1.4e-454.9e-324

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。

复数运算法则

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,347评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,435评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,509评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,611评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,837评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,987评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,730评论 0 267
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,194评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,525评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,664评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,334评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,944评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,764评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,997评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,389评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,554评论 2 349