文章目录
3.1 变量快速入门案例
package main
import "fmt"
func main() {
//定义变量/声明变量
var i int
//给i赋值
i = 10
//使用变量
fmt.Println("i=", i)
}
3.2 变量使用注意事项
-
变量表示内存中的一个存储区域
-
该区域有自己的名称(变量名)和类型(数据类型)
-
Golang变量使用的三种方式
- 第一种:指定变量类型,声明后若不赋值,使用默认值
- 第二种:根据值自行判定变量类型(类型推导)
- 第三种:省略var,注意:
:=
左侧的变量不应该是已经申明过的,否则会导致编译错误
package main
import "fmt"
func main() {
//golang变量使用的方式1:指定变量类型,声明后若不赋值,使用默认值(0)
var i int
fmt.Println("i =", i) //输出:i = 0
//golang变量使用的方式2:根据值自行判定变量类型(类型推导)
var num = 10.11
fmt.Println("num =", num)
//golang变量使用的方式3:省略var,注意:":="左侧的变量不应该是已经申明过的,否则会导致编译错误
//var name string name = "tom"
// := 不可以省略,否则错误
name := "tom"
fmt.Println("name =", name)
}
- 多变量声明
在编程中,有时我们需要一次性声明多个变量,Golang也提供这样的语法。
package main
import "fmt"
//定义全局变量
var n8 = 100
var n9 = 200
var name3 = "jack"
//上面的声明方式,也可以改成一次性声明
var (
n10 = 300
n11 = 400
name4 = "mary"
)
func main() {
//golang一次性声明多个变量
//方式1
var n1, n2, n3 int
fmt.Println("n1 =", n1, "n2 =", n2, "n3 =", n3) //n1 = 0 n2 = 0 n3 = 0
//方式2
var n4, name1, n5 = 100, "tom", 888 // = 前后一对一赋值
fmt.Println("n4 =", n4, "name1 =", name1, "n5 =", n5) //n4 = 100 name1 = tom n5 = 888
//方式3
n6, name2, n7 := 100, "tom", 888
fmt.Println("n6 =", n6, "name2 =", name2, "n7 =", n7) //n6 = 100 name2 = tom n7 = 88
//输出全局变量
fmt.Println("n8 =", n8, "name3 =", name3, "n9 =", n9) //n8 = 100 name3 = jack n9 = 200
fmt.Println("n10 =", n10, "name4 =", name4, "n11 =", n11) //n10 = 300 name4 = mary n11 = 400
}
- 该区域的数据值可以在同一类型范围内不断变化
- 变量在同一个作用域(在一个函数或者代码块)内不能重名
- 变量=变量名+值+数据类型
- Golang的变量如果没有赋初值,编译器会使用默认值,比如int默认值0,string默认值为空串,小数默认为0
3.3 程序中+号的使用
- 当左右两边都是数值型时,则做加法运算
- 当左右两边都是字符串,则做字符串拼接
3.4 数据类型的基本介绍
说明:官方中将string也作为基本数据类型,韩老师讲课中是将其分开的。
3.4.1 整数类型
- 整数的类型
类型 | 有无符号 | 占用存储空间 | 表示范围 |
---|---|---|---|
int8 | 有 | 1字节 | -128~127 |
int6 | 有 | 2字节 | − 2 15 -2^{15} −215 ~ 2 15 − 1 2^{15}-1 215−1 |
int32 | 有 | 4字节 | − 2 31 -2^{31} −231 ~ 2 31 − 1 2^{31}-1 231−1 |
int64 | 有 | 8字节 | − 2 63 -2^{63} −263 ~ 2 63 − 1 2^{63}-1 263−1 |
- int的无符号类型
类型 | 有无符号 | 占用存储空间 | 表示范围 |
---|---|---|---|
unit8 | 无 | 1字节 | 0~255 |
unit16 | 无 | 2字节 | 0~ 2 16 − 1 2^{16}-1 216−1 |
unit32 | 无 | 4字节 | 0~ 2 32 − 1 2^{32}-1 232−1 |
unit64 | 无 | 8字节 | 0~ 2 64 − 1 2^{64}-1 264−1 |
- int的其他类型—整型的类型
类型 | 有无符号 | 占用存储空间 | 表示范围 | 备注 |
---|---|---|---|---|
int | 有 | 32位系统4个字节 | − 2 31 -2^{31} −231 ~ 2 31 − 1 2^{31}-1 231−1 | |
64位系统8个字节 | − 2 63 -2^{63} −263 ~ 2 63 − 1 2^{63}-1 263−1 | |||
unit | 无 | 32位系统4个字节 | 0 ~ 2 32 − 1 2^{32}-1 232−1 | |
64位系统8个字节 | 0 ~ 2 64 − 1 2^{64}-1 264−1 | |||
rune | 有 | 与int32一样 | − 2 31 -2^{31} −231 ~ 2 31 − 1 2^{31}-1 231−1 | 等价int32,表示一个Unicode码 |
byte | 无 | 与unit8等价 | 0~255 | 当存储字符时,选用byte |
- 整型的使用细节
- Golang各整数类型分:有符号和无符号,int unit的大小和系统有关
- Golang的整型默认声明为int型
- 如何在程序查看某个变量的字节大小和数据类型
package main
import (
"fmt"
"unsafe"
)
func main() {
var n int64 = 10
fmt.Printf("n 的类型 %T n占有的字节数是 %d ", n, unsafe.Sizeof(n)) //n 的类型 int64 n占有的字节数是 8
}
- Golang程序中整型变量在使用时,遵守保小不保大的原则,即:在保证程序正确运行下,尽量使用占用空间小的数据类型。
3.4.2 小数类型/浮点型
- 小数类型
类型 | 占用存储空间 | 表数范围 |
---|---|---|
单精度float32 | 4字节 | -3.403E38~3.403E38 |
双精度float64 | 8字节 | -1.798E308~1.798E308 |
- 浮点型使用细节
- 浮点型的存储分为三部分:浮点数=符号位+指数位+尾数位。存储过程中,尾数部分可能丢失,造成精度损失(如果需要保存一个精度高的数,应该选用float64)
- Golang浮点类型有固定的范围和字段长度,不受具体OS的影响
- Golang的浮点数默认声明为float64类型
- 浮点型chang’l常量有两种表示形式
- 十进制数:如:5.12 .512(必须有小数点)
- 科学计数法:如: 5.1234 e 2 = 5.1234 × 1 0 2 5.1234e2=5.1234 \times 10^2 5.1234e2=5.1234×102, 5.12 e 12 = 5.12 / 1 0 2 5.12e12=5.12 / 10^2 5.12e12=5.12/102
- 通常情况下,应该使用float64,因为它比float32更精确。
3.4.3 字符类型
Golang中没有专门的字符类型,如果要存储单个字符(字母),一般使用byte来保存。Golang中的字符串是由字节组成的(传统的字符串是由字符组成的,而Golang中的字符是由字节保存,故Golang字符串是由字节组成的)。
package main
import "fmt"
func main() {
//演示golang中字符类型使用
var c1 byte = 'a'
var c2 byte = '0' //字符的0
//当我们直接输出byte值,就是输出了对应字符的码值
fmt.Println("c1 =", c1) //c1 = 97
fmt.Println("c2 =", c2) //c2 = 48
//如果我们希望输出对应字符,需要使用格式化输出
fmt.Printf("c1 = %c, c2 = %c", c1, c2) //c1 = a, c2 = 0
var c3 byte = '北'
fmt.Printf("c3 = %c", c3) //overflow溢出
var c4 int = '北'
fmt.Printf("c4 = %c, c4对应码值 = %d", c4, c4) //c4 = 北, c4对应码值= 21271
}
- 上述代码说明:
- 如果我们保存的字符在ASCII表可以直接保存到byte(即一个字节即可表示)
- 如果我们保存的字符对应码值大于255(如汉字),我们可以考虑使用int类型保存
- 如果我们需要按照字符的方式输出,那么我们可以格式化输出:
fmt.Printf("%c",c)
- 字符类型使用细节
- 字符常量是用单引号’括起来的单个字符。如:
var c byte = 'a'
。 - Go中允许使用转义字符’'来将其后的字符转变为特殊字符型常量。如:
var c char = '\n'
。 - Go语言的字符使用UTF-8编码:英文字母1个字节,汉字3个字节。
- 在Go中,字符的本质是一个整数,直接输出的是该字符对应的UTF-8编码的码值(所以需要格式化输出)。
- 可以直接给某个变量赋一个数字,然后按格式化输出%c会输出该数字对应的unicode字符。
- 字符类型是可以进行运算的,相当于一个整数,因为它都对应有unicode码。如,
var n1 = 10 + 'a'
,n1即107。
- 字符常量是用单引号’括起来的单个字符。如:
- 字符类型本质
- 字符型存储到计算机中,需要将字符对应的码值(整数)找出来
存储:字符–>对应码值–>二进制–>存储
读取:二进制–>码值–>字符–>读取 - 字符和码值的对应关系是通过字符编码表决定的
- Go语言的编码统一成了utf-8
- 字符型存储到计算机中,需要将字符对应的码值(整数)找出来
3.4.4 布尔类型
布尔类型占1个字节,适用于逻辑运算。
3.4.5 string类型
Go的字符串是由单个字节连接起来的,Go语言的字符串的字节使用utf-8编码表示unicode文本。
- string使用注意事项和细节
- Go语言的字符串的字节使用utf-8编码表示unicode文本,中文乱码不会产生。
- Go中字符串是不可变的:一旦赋值了,字符串就不能被修改。
- 字符串的两种表示形式:
- 双引号"",会识别转义字符
- 反引号``,以字符串的原生形式输出,包括换行和特殊字符,可以实现防止攻击、输出源代码等效果
- 字符串拼接方式
var str = "hello" + "world" str+= " haha!"
- 当一个拼接操作太长时,可以分行写,但是需要将+保留在上一行
3.5 基本数据类型的默认值
在Go中,默认值又叫零值。
数据类型 | 默认值 |
---|---|
整型 | 0 |
浮点型 | 0 |
字符串 | “” |
布尔类型 | false |
3.6 基本数据类型的相互转换
Go和Java/c不同,在不同类型的变量之间赋值时需要显式转换,不能自动转换。
基本语法:T(v)
,T是目标数据类型,v是需要转换的变量。如:float32(i)。
- 注意事项
- Go中,数据类型的转换可以是:表示范围小–>表示范围大,也可以是:表示范围大–>表示范围小。
- 被转换的是变量存储的数据(即值),变量本身的数据类型并没有变化。
- 在转换时,比如将int64转为int8,编译时不会报错,只是转换结果按照溢出处理,和我们希望的结果不一样,所以转换时需要考虑范围。
3.7 基本数据类型和string的转换
再次强调,官方将string作为基本数据类型,但是韩老师讲课中是分开的。
- 基本类型转string类型
fmt.Sprintf("%参数",表达式)
- 使用strconv包的函数
func FormatBool(b bool) string
func FormatFloat(f float64, fmt btye, prec, bitSize int) string
func FormatInt(i int64, base int) string
func FormatUnit(i unit64, base int) string
package main
import (
"fmt"
"strconv"
)
func main() {
var num1 int = 99
var num2 float64 = 23.456
var b bool = true
var myChar byte = 'h'
var str string
//方法一:使用fmt.Sprintf方法
str = fmt.Sprintf("%d", num1)
fmt.Printf("str type %T str = %v\n", str, str) //str type string str = 99
str = fmt.Sprintf("%f", num2)
fmt.Printf("str type %T str = %v\n", str, str) //str type string str = 23.456000
str = fmt.Sprintf("%t", b)
fmt.Printf("str type %T str = %v\n", str, str) //str type string str = true
str = fmt.Sprintf("%c", myChar)
fmt.Printf("str type %T str = %v\n", str, str) //str type string str = h
//方法二:使用strconv包的函数
var num3 int = 99
var num4 float64 = 23.456
var b2 bool = true
str = strconv.FormatInt(int64(num3), 10)
fmt.Printf("str type %T str = %v\n", str, str) //str type string str = 99
str = strconv.FormatFloat(num4, 'f', 10, 64) //'f'格式,10小数保留位数,64表示float64
fmt.Printf("str type %T str = %v\n", str, str) //str type string str = 23.4560000000
str = strconv.FormatBool(b2)
fmt.Printf("str type %T str = %v\n", str, str) //str type string str = true
//strconv包中海油一个函数Itoa
var num5 int = 4567
str = strconv.Itoa(num5)
fmt.Printf("str type %T str = %v\n", str, str) //str type string str = 4567
}
- string类型转基本类型
- 使用strconv包的函数
func ParseBool(str string)(value bool, err error)
func ParseFloat(str string, bitSize int)(f float64, err error)
func ParseInt(str string, base int, bitSize int)(i int64, err error)
func ParseUnit(str string, b int, bitSize int)(n unit64, err error) - 注意事项
string转成基本数据类型时,要确保string类型能够转成有效的数据,否则Go会将其直接转为零值。如将"hello"转成一个整数那么得到的是0,同理float=>0,bool=>false。
- 使用strconv包的函数
package main
import (
"fmt"
"strconv"
)
func main() {
var str string = "true"
var b bool
b, _ = strconv.ParseBool(str)
//strconv.ParseBool(str)会返回两个值(value bool, err arror),第二个error我们不关心,直接使用_
fmt.Printf("b type %T, b = %v\n", b, b) //b type bool, b = true
var str2 string = "12345"
var n1 int64
var n2 int
n1, _ = strconv.ParseInt(str2, 10, 64)
n2 = int(n1)
fmt.Printf("n1 type %T, n1 = %v\n", n1, n1) //n1 type int64, n1 = 12345
fmt.Printf("n2 type %T, n2 = %v\n", n2, n2) //n2 type int, n2 = 12345
var str3 string = "123.456"
var f1 float64
f1, _ = strconv.ParseFloat(str3, 64)
fmt.Printf("f1 type %T, f1 = %v\n", f1, f1) //f1 type float64, f1 = 123.456
}
3.8 指针
- 基本介绍
- 基本数据类型,变量存的就是值,也叫值类型
- 获取变量的地址,用&。如:
var num int
,获取num的地址:&num
- 指针类型,指针变量存的是一个地址,这个地址指向空间存的才是值。如:
var ptr *int = &num
- 获取指针类型所指向的值,使用:
*
。如:var ptr *int
,用*ptr
获取ptr指向的值
package main
import "fmt"
func main() {
var num int = 10
fmt.Println(&num) //0xc0000b4008
var ptr *int = &num //ptr是一个指针变量,ptr的类型是指向int的指针*int,ptr本身的值是&i
fmt.Println(*ptr) //10
//通过指针来修改值,但是不会修改指针地址
*ptr = 100
fmt.Println(*ptr) //100
fmt.Println(ptr) //0xc0000b4008
}
- 指针的使用细节
- 值类型,都有对应的指针类型,形式为
*数据类型
,如*int, *float32
- 值类型包括:基本数据类型:int系列、float系列、bool、string、数组和结构体struct
- 值类型,都有对应的指针类型,形式为
3.9 值类型和引用类型
- 值类型和引用类型的说明
- 值类型:基本数据类型:int系列、float系列、bool、string、数组和结构体struct。
- 引用类型:指针、slice切片、map、管道chan、interface等都是引用类型。
- 值类型和引用类型的使用特点
- 值类型:变量直接存储值,内存通常在栈中分配。
- 引用类型:变量存储的是一个地址,这个地址对应的空间才真正存储数据,内存通常在堆上分配,当没有任何变量应用这个地址时,该地址对应的数据空间就成为一个垃圾,由GC来回收。
3.10 标识符的命名规范
- 标识符概念
Golangg对各种变量、方法、函数等命名时使用的字符序列称为标识符。 - 命名规则
- 由26个英文字母大小写,0-9,_组成。
- 数字不可以开头。
- Golang中严格区分大小写。
- 标识符不能包含空格。
- 下划线“_”本身在Go中是一个特殊的标识符,称为空标识符,可以代表任何其他的标识符,但是它对应的值会忽略(如:忽略某个返回值)。所以仅能被作为占位符使用,不能作为标识符使用。
- 不能以系统保留关键字作为标识符(共25个)。
- 标识符命名注意事项
- 包名:保持package的名字和目录保持一致,尽量采取有意义的包名,剪短有意义,不要和标准库冲突。
- 变量名、函数名、常量名:采用驼峰命名法。
- 如果变量名、函数名、常量名首字母大写,则可以被其他的包访问;如果首字母小写,则只能在本包中使用。(可以简单地理解为,首字母大写是公开的,首字母小写是私有的),在Go中没有public、private关键字。
- 系统保留关键字
- 系统的预定义标识符