go语言之变量基础

标识符

规则

标识符用来表示函数、变量、常量、类型、语句标签和包的命名,命名标准如下:

  • 字母或下划线开头
  • 后面任意数量的字符、数字、下划线(区分大小写)

命名风格

go对于函数、变量、常量等有一些自己的命名风格,在语法上不是强制性的:

  • 尽量使用短名称
  • 单词组合时,采用"驼峰式"
  • 包名总是由小写字母组成

变量

声明

go中对变量的声明,有以下几种方式:

// 1. var  name  type = expression  同时指定类型和表达式
var name string = "Jim"

// 2. var name type   只指定类型
var name string 

// 3. var name = expression  只有表达式(go根据表达式的返回值类型自动推导类型)
var name = "Jim" 
var age = getAge() 

// 4. name := expression   短变量声明,无需var关键字,:=可以表达变量声明的意思。根据表达式返回值推导类型
name := "Jim"  // 推导name为string类型   
age := getAge() // 推导 age为int类型

go除了支持上面的单变量声明,还支持声明变量列表:

// 1. var name1, name2, name3  type
var v1, v2, v3 string  // 三个变量必须是相同类型的
var v1 int, v2 string  // 错误语法

// 2. var name1, name2, name3 = expressions
var name1, name2, name3 = 1, true, "hello"  // 必须每个变量都有初始值,否则编译错误

// 3. name1, name2 := expressions
v1, v2 := 1, "hello"  // 必须每个变量都有初始值

go语言中提供了多种变量声明的方式,主要目的还是为了提高程序员编程效率,因此我们应该合理的使用这些声明方式:

  • var关键字声明一般用于跟初始化表达式类型不一致局部变量、或者后面才赋值的变量、或包变量
  • 短变量,只能用于函数内部局部变量声明,另外可用于var关键字之外的场景

局部变量和全局变量

局部变量是声明在{}里面的变量,包括函数内、循环语句内等。作用域也只在{}内部,

全局变量函数外部的变量称为全局变量,作用域在包内的任意地方。对于全局变量不区分声明和引用位置的前后,可以在任意位置声明,也可以在任意位置引用。

指针

go中的指针概念与C++的指针不完全相同。指针的类型为* type&为变量取地址操作符,*为指针解引用操作符,但是指针不支持运算(指针的运算可以通过unsafe包和uintptr实现),如:

age := 18
var p * int
p = &age  // p 指向 age

// 指针不支持运算
p = p + 1 // 错误
p++  // 错误

new函数

new函数可以用来创建变量:new(T)用来创建一个未命名的T类型的变量,并初始化为零值,返回地址。

p := new(int) // new创建一个int变量,将地址返回,p是一个(*int)指针
fmt.Println(*p)  

与C++不同,new创建的变量和普通局部变量没有什么不同,并不能决定变量是在栈上还在堆上

func test() {
    var age = 18  // 普通变量,在栈帧上
    var *p = new(int)  // *p 也是栈帧上的一个普通变量
    fmt.Println(age, *p)    
}

简单来讲,变量一般存在与栈帧或者,在go里面这个是编译器自动决定的,程序员无法指定。go的设计原则认为,手动指定变量的存储位置容易引入bug,另外go是通过GC来管理堆内存的,可以自动释放内存。因此go为了简化内存管理,自动判断变量应该存储于栈帧还是堆,大概的原则为:

  • golang编译器会尽可能将变量分配在函数的栈帧。因为分配速度快,且函数调用结束直接释放。
  • 如果一个变量非常大,则将其分配在堆上。操作系统的栈是有限长度的。linux默认8MB。
  • 如果变量发生了逃逸,则将其分配在堆上。比如当函数返回一个局部变量的地址时,则此变量会被分配在堆上。go对变量逃逸的分析是机械的、不灵活的,这也会造成将非必要的一些变量分配到堆上,对于内存和性能要求较高的地方需要注意。

多重赋值和空标识符_

go允许几个变量同时被赋值

  var x, y int
x, y = 1, 3
x, y = y, x  // 交换x、y的变量
x, y = y, x+y  

go会保证在实际更新变量前,右边所有的表达式被推演。

可以将不需要的值赋给空标识符'_'

func getNameAge() (int, string) {
	age, name := 18, "Jim"
	return age, name
}

func main() {
	age, _ := getNameAge()   // 空标识符,起到占位的作用,否则编译错误
	fmt.Println(age)

	_, name := getNameAge() // 空标识符,起到占位的作用,否则编译错误
	fmt.Println(name)
}

type类型声明

go提供了type关键字,用于声明新的类型。有点类似于C++中的typedef,但又不完全相同:

type newType underlying-type

type PriceType float64  // 定义了新类型,基础类型为float64
type VolumeType float64 // 定义了新类型

func main() {
	var oilPrice PriceType = 7.8 // 使用新类型定义变量。可以表示为油价为 7.8 元/升
	var volume VolumeType = 10.4 // 表示加了10.4升 油

	var amount float64 = float64(oilPrice) * float64(volume) //计算总金额
	fmt.Println(amount)
}

type关键字在已有的具名或者匿名类型上,建立一个新的类型。新类型拥有底层类型一样的操作(算术运算、比较运算等)。在go中不同类型的数据是不能在一起运算的(无论新类型合适基础类型)

var x int = 2
var y float64 = 3.4

// z := x * y   /// 错误,不同类型不能在一起运算
z := float64(x) * y  // 将x转换为float64类型
fmt.Println(z)

不同类型间的数据进行运算,需要使用显示类型转换,每个类型都有一个对应的类型转换操作符:T(x),表示将x值/变量转换为T类型。

  • 对于底层类型相同的类型,类型转换不会改变的值的表达方式,如上例中的PriceType和VolumeType之间的转换。
  • 对于底层类型不同的类型,类型转换会改变值的表达方式,如浮点转换为整型会丢失小数部分。

作用域和生命周期

生命周期是一个运行时属性,表示变量在程序执行期间能被程序的其他部分所引用的起止时间。

作用域是一个编译时属性,表示声明在程序文本中出现的区域。作用域一般包括:

  • {}语法块如函数、循环体等
  • 词法块,没有被{}显示包含的声明代码,如if 、for、switch语句
  • 包,声明在同一个包的标识符(可以在不同文件)
  • 文件,当一个包被导入时,只能在该导入文件中有效,其他文件中无效(即使是同一个包的不同文件)

有些情况下当程序运行到标识符的作用域之外时,该标识符的声明周期也就结束了,但有时也不会结束(如函数中的局部变量发生了逃逸),当一个变量逃逸出它声明的区域时,我们无法再通过此变量名引用该变量,因为此时已经出了其作用域;但是该变量的生命周期还未结束,因为我们可以通过其他标识符引用此变量。

func getAge() {
    var age int = 18  // age的作用域仅在getAge()函数中,出了此函数,便无法通过age引用此变量。
    return &age 
}

func test() {
    p := getAge()   // 此时age变量的生命周期依然未结束,因为我们可以通过p来引用访问此变量
    fmt.Println(*p)
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 很高兴为你推荐 Go 语言的中文基础入门教材。我推荐的是 "Go 入门指南" 这本书。这本书由阮一峰编写,是一本非常适合初学者学习 Go 的教材。它从 Go 语言的基本语法开始,一直讲到 Go 语言的高级特性,包括并发编程,网络编程,以及 Go 语言的工具链等。 另外,还有 "Go 编程基础" 这本书也是一本很好的 Go 语言入门教材。这本书由 AstaXie 编写,也是从 Go 语言的基本语法开始讲解,讲述的内容包括 Go 语言的数据类型、流程控制、函数、面向对象编程、并发编程等。 希望这些推荐能帮到你。 ### 回答2: 推荐《Go语言圣经》作为最新的中文基础入门教材,该书由美国Go语言的创始人之一Alan A.A. Donovan和Google工程师Brian W. Kernighan合著,由人民邮电出版社出版。该书以深入浅出的方式介绍了Go语言基础知识和核心概念,适合初学者入门使用。 《Go语言圣经》全书分为11个章节,从基础概念、基本语法和数据类型开始,逐步介绍了函数、指针、结构体、方法、接口、并发等高级特性。每个章节都配备了大量的示例代码和练习题,帮助读者理解和巩固所学知识。 这本书的亮点之一是它与Go语言官方文档相结合的方式,使得读者能够更好地理解和运用所学知识。此外,在讲解基础知识的同时,书中也涉及了一些实际应用场景,为读者提供了实践的机会。 《Go语言圣经》由于由Go语言的创始人之一和Google工程师合著,因此具有权威性和深度。该书的语言通俗易懂,适用于零基础或其他语言背景的读者。通过阅读和实践,读者能够掌握Go语言的基本语法和特性,为进一步的学习和应用打下基础。 ### 回答3: 在Go语言领域,有一本备受推荐和认可的中文基础入门教材是《Go语言入门指南》。这本教材由暮色短发撰写,是一本深受学习者欢迎的教程。 《Go语言入门指南》首先从介绍Go语言的历史和特点开始,帮助读者快速了解该语言的背景和优势。接着,教材详细讲解了Go语言的基本语法、数据类型、变量、函数、流程控制以及面向对象编程等核心概念。每个知识点都配有大量的代码实例和解释,让读者能够通过实践理解和巩固所学知识。 此外,《Go语言入门指南》还涵盖了常用的标准库和Go语言的并发编程,对如何使用这些特性进行了详细讲解。通过学习这些内容,读者可以掌握Go语言基础知识,并能够进行简单的项目开发。 这本教材的优点在于简洁明了,易于理解。作者结合自己的经验和实践,将复杂的概念和知识点讲解得浅显易懂。同时,配有丰富的实例和练习,帮助读者巩固所学内容。 总之,《Go语言入门指南》是我强烈推荐的Go语言基础教材。它适合初学者入门,也适合有一定编程基础的开发者进一步学习和提升。通过阅读这本教材,你可以有效地掌握Go语言基础知识,并能够运用到实际的项目开发中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值