一、变量
- 变量介绍
变量相当于内存中一个数据存储空间的表示
-
变量使用步骤
声明、赋值、使用
-
示例
package main import "fmt" func main(){ // 先声明,再赋值,再使用 //1.变量声明 var age int //2.变量赋值 age = 19 //3.变量使用 fmt.Println("age = ", age) // 同时声明赋值(常用) var age2 int = 10 fmt.Println("age2 = ", age2) //赋值和类型不匹配会报错。 var num int = 12.23 fmt.Println("num = ", num) }
-
全局变量和局部变量
全局变量:定义再函数外的变量
局部变量:定义再函数内的变量
-
变量使用的4中方式
-
指定变量类型并赋值
var num int = 10
-
指定变量类型,单不赋值,用默认值
var num int
-
不指定变量类型,根据值自动判断变量类型(自动类型推断)
var num = "jack"
-
省略声明和类型
sex := "男"
-
-
示例
package main import "fmt" //全局变量:定义再函数外的变量 var n1 = 200 var n2 = 3.2 //简化写法: 一次声明多个变量 var ( n3 = 200 n4 = "tom" ) func main() { //1. 指定变量类型并赋值 var num int = 10 fmt.Println("num = ", num) //2. 指定变量类型不赋值,用默认值 var num2 int fmt.Println("num2 = ", num2) //3. 不指定变量类型,根据值自动判断变量类型(自动类型推断) var num3 = "jack" fmt.Println("num3 = ", num3) //4. 省略声明和类型 sex := "男" fmt.Println("sex = ", sex) //一次声明多个变量 var n5, n6, n7 int fmt.Println(n5) fmt.Println(n6) fmt.Println(n7) }
二、基本数据类型
1. 整数类型(int)
有符号整数
类型 | 有无符号 | 占用存储空间 | 表数范围 |
---|---|---|---|
int8 | 有 | 1个字节 | −27-2^7−27 ~ 27−12^7-127−1 (-128~127) |
int16 | 有 | 2个字节 | −215-2^{15}−215 ~ 215−12^{15}-1215−1 (-32768 ~ 32767) |
int32 | 有 | 4个字节 | −231-2^{31}−231 ~ 231−12^{31}-1231−1 (-2147483648 ~ 2147483647) |
int64 | 有 | 8个字节 | −263-2^{63}−263 ~ 263−12^{63}-1263−1 |
无符号整数类型
类型 | 有无符号 | 占用存储空间 | 表数范围 |
---|---|---|---|
uint8 | 无 | 1字节 | 0~255 |
uint16 | 无 | 2字节 | 0~ 2162^{16}216 -1 |
uint32 | 无 | 4字节 | 0~2312^{31}231-1 |
uint64 | 无 | 8字节 | 0~2632^{63}263-1 |
其他整数类型
类型 | 有无符号 | 占用存储空间 | 表数范围 |
---|---|---|---|
int | 有 | 32位系统-4字节 64位系统-8字节 | -2312^{31}231 ~ 2312^{31}231-1 -2632^{63}263 ~ 2632^{63}263-1 |
uint | 无 | 32位系统-4字节 64位系统-8字节 | 0 ~ 2322^{32}232-1 0 ~ 2642^{64}264-1 |
rune | 有 | 等价int32 | -2312^{31}231 ~ 2312^{31}231-1 |
byte | 无 | 等价uint8 | 0 ~ 255 |
说明:golang的整数类型,默认声明为int类型。使用原则:保证程序正常运行下,尽量使用占用空间小的数据类型。
2. 浮点类型(float)
能够存放小数值,比如:3.23、0.23、-4.23等等。
种类包括两种:float32、 float64
类型 | 存储空间 | 表数范围 |
---|---|---|
float32 | 4字节 | -3.403E38 ~ 3.403E38 |
float64 | 8字节 | -1.798E308 ~ 1.798E308 |
说明:
- 底层存储空间和操作系统无关。
- 浮点类型底层存储:符号位 + 指数位 + 尾数位,尾数位只存了一个大概,会有精度损失。
- 减少精度损失,建议用float64
- 默认的类型为:float64
示例:
package main
import "fmt"
func main() {
//定义浮点类型数据
var num1 float32 = 3.14
fmt.Println(num1)
//可以表示正浮点数,也可以表示负浮点数
var num2 float32 = -3.14
fmt.Println(num2)
//浮点数可以用十进制表示,也可以用科学计数法表示,其中E 大小写都行
var num3 float32 = 314e-2
fmt.Println(num3)
var num4 float32 = 314e+2
fmt.Println(num4)
var num5 float32 = 314e+2
fmt.Println(num5)
var num6 float32 = 314e+2
fmt.Println(num6)
//浮点数有精度损失,建议使用float64
var num7 float32 = 362.000000888
fmt.Println(num7)
var num8 float64 = 362.000000888
fmt.Println(num8)
//默认的浮点类型为:float64
var num9 = 2.34
fmt.Printf("num9对应的默认的类型为:%T", num9)
}
运行结果:
3.14
-3.14
3.14
31400
31400
31400
362
362.000000888
num9对应的默认的类型为:float64
3. 布尔类型(bool)
bool
只有两个值,分别为:true
,false
。
存储时只占用1个字节。应用场景:用于流程判断
示例:
package main
import "fmt"
func main() {
var flag1 bool = true
fmt.Println(flag1)
var flag2 bool = false
fmt.Println(flag2)
var flag3 bool = 3 < 8
fmt.Println(flag3)
}
结果:
true
false
true
4. 字符类型(byte)
go语言中,没有专门的字符类型,如果存单个字符时,一般使用byte来储存,就是字符对应的数字。并且go语言中字符是使用utf-8进行编码的。
代码示例:
package main
import "fmt"
func main() {
//定义字符类型数据
var c1 byte = 'a'
fmt.Println(c1) // 打印出来是97,a所对应的数字
var c2 byte = '6'
fmt.Println(c2) //打印出来是:54
var c3 byte = '('
fmt.Println(c3 + 10) //打印出来是:40;可以直接参与运算
//字母,数字,标点等字符,底层是按照ASCII进行存储
var c4 int = '中'
fmt.Println(c4) //对应的码值是:20013,超出了byte类型的最大值(255),所以可以用int表示
//汉字字符,底层对应的是Unicode码值
//go语言中,字符使用的是UTF-8编码(Unicode是对应的字符集,UTF-8是Unicode的其中的一种编码方案)
//如果想显示对应的字符,输出是必须格式化输出
var c5 byte = 'A'
fmt.Printf("c5对应的具体的字符为:%c", c5)
}
执行结果:
97
54
50
20013
c5对应的具体的字符为:A
以下是ASCII表,以供后续查看。
转义字符:
\转义字符:将后面的字母表示特殊含义
转义符 | 含义 | Unicode值 |
---|---|---|
\b | 退格(backspace) | \u0008 |
\n | 换行 | \u000a |
\r | 回车 | \u000d |
\t | 制表符(tab) | \u0009 |
\ " | 双引号 | \u0022 |
\ ’ | 单引号 | \u0027 |
\ \ | 反斜杠 | \u005c |
5. 字符串类型(string)
示例:
package main
import "fmt"
func main() {
//定义字符串
var s1 string = "这是一个新定义的字符串"
fmt.Println(s1)
//字符串是不可变的:指的是字符串一旦定义好,里面的值是不能直接改变的,如果想改,必须通过将string转成[]byte切片,修改切片内容,然后再转成string
var s2 string = "abc"
//s2[0] = 't'//直接修改,编译器会报错
s2 = "def" //这里能正确赋值,如何解释呢?其实这里只是将s2所指的内存地址发生了变化,不是真的将"abc"的值改成了"def"。"abc"的值还存在
fmt.Println(s2)
//字符串的表示形式
//没有特殊字符,用双引号
var s3 string = "无特殊字符,用双引号"
fmt.Println(s3)
//有特殊字符,用反引号``
var s4 string = `package main import "fmt"`
fmt.Println(s4)
//字符串拼接
var s5 string = "这是一个字符串" + "拼接"
s5 += ",得到一个新字符串"
fmt.Println(s5)
}
运行结果:
这是一个新定义的字符串
def
无特殊字符,用双引号
package main import "fmt"
这是一个字符串拼接,得到一个新字符串
6. 基本数据类型默认值
go语言中,如果定义的变量,并没有对变量进行赋值,默认会给一个默认值(零值)
以下表格是默认值:
数据类型 | 默认值 |
---|---|
整数类型(int) | 0 |
浮点类型(float) | 0 |
布尔类型(bool) | false |
字符串类型(string) | “” |
示例:
package main
import "fmt"
func main() {
//整数
var a int
fmt.Println(a)
//浮点型
var b float32
fmt.Println(b)
//浮点型
var c float64
fmt.Println(c)
//布尔型(bool)
var d bool
fmt.Println(d)
//字符串类型
var e string
fmt.Println("字符串类型:" + e)
}
执行结果:
0
0
0
false
字符串类型:
7. 基本数据类型之间的转换
go语言类型转换为显示转换(强制转换),转换的语法为:T(v),将值v转换为类型T
T:要转成的数据类型
v:需要转换的变量
注意:这里不包括string类型
示例:
package main
import "fmt"
func main() {
//int类型转换float类型
var t1 int = 10
//var t2 float32 = t1 //这种写法,编译不通过。
fmt.Println(t1)
var t2 float32 = float32(t1) //这种才能转换成功
fmt.Println(t2)
//这里需注意:t1的类型其实还是int类型,只是将t1的值10转换为了float32而已,t1还是int类型
fmt.Printf("%T", t1) //int
//将int64转换为int8时,编译不会报错,但有可能会造成数据溢出
var t3 int64 = 999999
var t4 int8 = int8(t3)
fmt.Println(t4) //63 数据不是999999,而是63,数据溢出了。
//参与运算时,数据类型必须匹配
var t5 int32 = 10
var t6 int64 = int64(t5) + 30 // 等号左右,数据类型一定要一致
fmt.Println(t6)
//参与运算时,两个参数类型要一致
var t7 int64 = 10
var t8 int8 = int8(t7) + 127 //编译通过,但结果溢出
//var t9 int8 = int8(t7) + 128 //编译不通过
fmt.Println(t8) //结果为:-119 溢出了
//fmt.Println(t9)
}
运行结果:
10
10
int63
40
-119
8. 基本数据类型转String
有两种方式:
方式一:fmt.Sprintf(“%参数”,表达式)
func Sprintf(format string, a ...interface{}) string
Sprintf函数作用:根据format参数生成格式化的字符串并返回该字符串
代码示例:
package main
import "fmt"
func main() {
var n1 int = 10
var n2 float32 = 3.14
var n3 bool = false
var n4 byte = 'a'
var s1 string = fmt.Sprintf("%d", n1) // %d:打印整数
fmt.Printf("s1对应的类型是:%T,s1 = %q \n", s1, s1) //%T: 打印类型;%q: 双引号字符串
var s2 string = fmt.Sprintf("%f", n2) // %f:打印浮点数
fmt.Printf("s2对应的类型是:%T,s2 = %q \n", s2, s2)
var s3 string = fmt.Sprintf("%t", n3) // %t:打印布尔值
fmt.Printf("s3对应的类型是:%T,s3 = %q \n", s3, s3)
var s4 string = fmt.Sprintf("%c", n4) // %c:打印字符
fmt.Printf("s4对应的类型是:%T,s4 = %q \n", s4, s4)
}
执行结果:
s1对应的类型是:string,s1 = "10"
s2对应的类型是:string,s2 = "3.140000"
s3对应的类型是:string,s3 = "false"
s4对应的类型是:string,s4 = "a"
方式二:使用strconv包的函数
代码示例:
package main
import (
"fmt"
"strconv"
)
func main() {
var n1 int = 9
//1.FormatInt()参数:第一个参数必须是int64类型,第二个参数是几进制,此处标识十进制
var s1 string = strconv.FormatInt(int64(n1), 10)
fmt.Printf("s1对应的类型是:%T, s1 = %q \n", s1, s1)
var n2 float64 = 2.31
//2.FormatFloat()参数:第一个参数:n2, 第二个参数:'f'(-ddd.dddd), 第三个参数:8 保留小数点后面8位,第四个参数:n2参数为float64类型
var s2 string = strconv.FormatFloat(n2, 'f', 8, 64)
fmt.Printf("s2对应的类型是:%T, s1 = %q \n", s2, s2)
var n3 bool = true
var s3 string = strconv.FormatBool(n3)
fmt.Printf("s3对应的类型是:%T, s3 = %q \n", s3, s3)
}
执行结果:
s1对应的类型是:string, s1 = "9"
s2对应的类型是:string, s1 = "2.31000000"
s3对应的类型是:string, s3 = "true"
9. String转基本数据类型
使用strconv包
代码示例:
package main
import (
"fmt"
"strconv"
)
func main() {
// string --> bool
var s1 string = "true"
var b bool
//ParseBool 这个函数返回两个值:(value bool, err error) value:转换后布尔类型的数据;err:出现错误时的错误信息
//现在我们只关注转后后的布尔类型的数据,错误数据先忽略,忽略用下划线(_)表示
b, _ = strconv.ParseBool(s1)
fmt.Printf("b的类型是:%T, b = %v \n", b, b) //%v: 打印结构体
//string --> int64
var s2 string = "20"
var num1 int64
num1, _ = strconv.ParseInt(s2, 10, 64)
fmt.Printf("num1的类型是:%T, num1 = %v \n", num1, num1)
//string --> float32/float64
var s3 string = "2.23"
var f1 float64
f1, _ = strconv.ParseFloat(s3, 64)
fmt.Printf("f1的类型是:%T, f1 = %v \n", f1, f1)
//以下是注意信息:
//string向基本数据类型转换的时候,一定要确保string类型能够转成有效的数据类型,否则最后得到的结果就是按照对应类型的默认值输出
var s4 string = "go"
var b1 bool
b1, _ = strconv.ParseBool(s4)
fmt.Printf("b1的类型是:%T, b1 = %v \n", b1, b1)
var s5 string = "go"
var num2 int64
num2, _ = strconv.ParseInt(s5, 10, 64)
fmt.Printf("num2的类型是:%T, num2 = %v \n", num2, num2)
}
执行结果:
b的类型是:bool, b = true
num1的类型是:int64, num1 = 20
f1的类型是:float64, f1 = 2.23
b1的类型是:bool, b1 = false
num2的类型是:int64, num2 = 0
三、复杂数据类型(指针)
指针:存储内存地址(0xc000102058)的数据类型。
//定义:
var age int = 30
//将age变量的内存地址赋值给ptr指针变量
var ptr *int = &age// &age:存储age变量内存地址的值(0xc000102058)
两个重要的符号:
- &:取内存地址
- *:根据地址取值
代码示例:
package main
import "fmt"
func main() {
var age int = 10
fmt.Println("age的存储空间地址为:", &age)
//定义指针变量:
//var:变量声明;
//ptr:指针变量名称;
//*int:ptr对应的类型,是个指针类型(指向int类型的指针)
//&age: 内存地址,是ptr变量具体的值
//将age的内存地址赋值给指针变量ptr
var ptr *int = &age
fmt.Println(ptr)
fmt.Println("ptr本身这个存储空间的地址为:", &ptr)
//想获取ptr这个指针或者这个地址指向的那个数据
fmt.Printf("ptr指向的值为:%v \n", *ptr) //ptr指向的数值为:10
//可以通过指针改变指向的值
*ptr = 20
fmt.Println("通过指针改变age的值,改变后的结果为:", age) //20
}
执行结果:
age的存储空间地址为: 0xc000018098
0xc000018098
ptr本身这个存储空间的地址为: 0xc000006030
ptr指向的值为:10
通过指针改变age的值,改变后的结果为: 20
几个注意的点:
-
指针变量接收的值一定是地址值
//以下为伪代码 var age int = 10 fmt.Println(age) var ptr *int = num //这是不对的,指针必须赋值为地址即&age
-
指针变量的地址值类型必须匹配
//伪代码
var num int = 10
fmt.Println(num)
var ptr *float32 = &num //这是错误的写法,因为num的类型是int。指针的类型必须为*int
-
基本数据类型(又叫值类型),都有对应的指针类型,形式统一为:*数据类型
比如:
int的对应指针就是*int
float32对应的指针类型就是*float32
…