go语言基础第二课-变量和数据类型
tags:
- golang
- 2019尚硅谷
categories:
- golang
- 变量
- 数据类型
文章目录
第一节 go语言变量介绍
1. 变量概念
- 变量相当于内存中一个数据存储空间的表示,你可以把变量看做是一个房间的门牌号,通过门牌号我们可以找到房间,同样的道理,通过变量名可以访问到变量(值)。
2. 变量使用的基本步骤
- 声明变量(有人也叫: 定义变量)
- 声明赋值
- 声明使用
- 加号的使用(提前预习)
- 当左右两边都是数值型时,则做加法运算
- 当左右两边都是字符串,则做字符串拼接
package main
import "fmt"
func main() {
//定义变量/声明变量
var i int
// 给 i 赋值
i = 10
// 使用变量
fmt.Println("i=", i)
// +的两种使用
var k, p int
var s1, s2 = "hello", "world"
p = k + i
var s = s1 + s2
fmt.Println("p=", p)
fmt.Println("s=", s)
}
3.变量使用注意事项
- 变量表示内存中的一个存储区域,该区域的数据值可以在同一类型范围内不断变化
- 该区域有自己的名称(变量名)和类型( 数据类型),变量在同一个作用域内不能重名,在作用空间中可以重名。(如下代码,全局name和main函数的name)
- Golang变量使用的三种方式
(1)第一种:指定变量类型,声明后若不赋值,使用默认值
(2)第二种:根据值自行判定变量类型(类型推导)
(3)第三种:省略var, 注意:=左侧的变量不应该是已经声明过的,否则会导致编译错误 - 多变量声明。在编程中,有时我们需要一次性声明多个变量,Golang也提供这样的语法
- 全局变量的声明。推荐var()
package main
import "fmt"
// 定义全局变量
// var p1 = 100
// var p2 = 200
// var pname = "jack"
//var p1, p2, pname = 100, 200, "jack"
//(这种赋值不能定义全局变量)p1, p2, pname := 100, 200, "jack"
// 全局变量的name, 会被mian函数中的name赋值替代
var(
p1 = 100
p2 = 200
name = "jack"
)
func main() {
//变量的使用方式一
//第一种:指定变量类型,声明后若不赋值,使用默认值
// int 的默认值为0,其他变量的默认值看数据类型章节
var i int
fmt.Println("i=", i)
//变量的使用方式二
//第二种:根据值自行判定变量类型(类型推导)。动态编程语言的特点python,php
// go语言是快速的、静态类型的编译型语言,感觉却像动态类型的解释型语言。
var num = 10.11
fmt.Println("num=", num)
//变量的使用方式三
//第三种:省略var, 注意:=左侧的变量不应该是已经声明过的,否则会导致编译错误(:绝对不能省掉)
// 等价于 var name string name = "tom"
name := "tom"
fmt.Println("name=", name)
//多变量声明方式一(一次声明多个变量)
var n1, n2, n3 int
fmt.Println("n1=", n1, "n2=", n2, "n3=", n3)
//多变量声明方式二(一次声明多个不同类型变量)
var n4, name1, n5 = 100, "tom", 888
fmt.Println("n4=", n4, "name1=", name1, "n5=", n5)
//多变量声明方式三(一次声明多个不同类型变量)
n7, name2, n8 := 100, "xiaoming", 888
fmt.Println("n7=", n7, "name2=", name2, "n8=", n8)
// 在go函数外部定义的变量就是全局变量
fmt.Println("p1=", p1, "p2=", p2, "name=", name)
}
第二节 Go语言的数据类型
1. 基本数据类型-整数类型
- 整数类型前四种:占用字节和表示位数如下:
- 整数类型后四种:占用字节和表示位数如下:
- Golang各整数类型分:有符号和无符号,int uint的大小和系统有关。
- Golang的整型默认声明为int型
- 如何在程序查看某个变量的字节大小和数据类型。看下面例子
- Golang程序中整型变量在使用时,遵守保小不保大的原则,即:在保证程序正确运行下,尽量使用占用空间小的数据类型。[如: 年龄]
- bit:计算机中的最小存储单位。byte:计算机中基本存储单元。[二进制再详细说]
package main
// import "fmt"
// import "unsafe"
import(
"fmt"
"unsafe"
)
func main() {
// 如何在程序查看某个变量的字节大小和数据类型
var n1 int64 = 100
// unsafe包的函数,可以返回n1变量占用的字节数
fmt.Printf("n1 的数据类型 %T \n n1占用的字节大小 %d", n1, unsafe.Sizeof(n1))
}
2. 基本数据类型-浮点类型
- 浮点类型就是用于存放小数的,比如1.20.23 -1.911
- 不同的浮点类型区别在于:表示的范围和精度不同.
- float64位的范围和精度更高。通常情况下,应该使用float64,因为它比float32更精确。
- 关于浮点数在机器中存放形式的简单说明,浮点数=符号位+指数位+尾数位
- 浮点类型都是有符号的。
- 默认声明的浮点类型为:float64
- 浮点类型有固定的范围和字段长度,不受具体OS(操作系统)的影响。
- 浮点型的存储分为三部分:符号位+指数位+尾数位在存储过程中,精度会有丢失
// 浮点注意事项:
// 十进制表示形式
num3 := 5.12
num4 := .234 //=>0.234
fmt. Println("num3=", num3, "num4=", num4)
//科学计数法表示e或E
num8 := 5.1234e2 //=> 5.1234 * 10^2
num9 := 5.1234E-2 //=> 5.1234 * 10^-2
fmt. Println("num8=", num8, "num9=", num9)
3. 基本数据类型-字符类型
- Golang中没有专门的字符类型,如果要存储单个字符(字母),一 般使用byte来保存。
- 字符串就是一串固定长度的字符连接起来的字符序列。Go的字符串是由单个字节连接起来也就是说对于传统的字符串是由字符组成的,而Go的字符串不同,它是由字节组成的
[官方将string归属到基本数据类型. https://tour.go-zh.org/basics/11 ] - 如果我们保存的字符在ASCI表的比如[0-1, a-z,A-Z ]直接可以保存到byte
- 如果我们保存的字符对应码值大于255,这时我们可以考虑使用int类型|
- 如果我们需要安装字符的方式输出,这时我们需要格式化输出,即fmt.Printf(“c3=%c\nc3对应的码值%d”, c3, c3)
package main
import "fmt"
// 演示golang中字符类型的使用
func main() {
var c1 byte = 'a'
var c2 byte = '0'
// 我们直接输出,实际上输出的是字符对应的ASCII码值
fmt.Println("c1:", c1, "\nc2:", c2)
// 如果想要输出对应的的字符的话,需要使用格式化的输出方式
fmt.Printf("c1=%c c2=%c\n", c1, c2)
//var c3 byte = '北' constant 21271 overflows byte
var c3 int = '北'
fmt.Printf("c3=%c\nc3对应的码值%d", c3, c3)
}
- 字符常量是用单引号(")括起来的单个字符。例如: var c1 byte=‘a’ var c2 int=‘中’ var c3 byte= ‘9’
- Go中允许使用转义字符"'来将其后的字符转变为特殊字符型常量。例如: var c3 char = ‘\n’ // '\n’表示换行符
- Go语言的字符使用UTF-8编码(英文字母一个字节,汉字占用三个字节)
- 在Go中,字符的本质是一个整数,直接输出时,是该字符对应的UTF-8编码的码值。
- 可以直接给某个变量赋一个数字,然后按格式化输出时%c ,会输出该数字对应的unicode字符.
- 字符类型是可以进行运算的(按照码值进行运算的),相当于一个整数,因为它都对应有Unicode码.
- 字符型存储到计算机中,需要将字符对应的码值(整数)找出来
- 存储:字符 -> 对应码值 - > 二 进制 ->存储
- 读取:二进制 -> 码值 -> 字符 -> 取出
- 字符和码值的对应关系是通过字符编码表决定的(是规定好)
- Go语言的编码都统一成了utf-8,和其它的编程语言来说。非常的方便,很统一,在也没有编码的困扰了。
4. 基本数据类型-布尔类型
- 布尔类型也叫bool类型,bool类 型数据只允许取值true和false(给一个布尔类型的变量赋值1,肯定会报错)
- bool类型占1个字节。
- boolean类型适于逻辑运算,一般用于程序流程控制[注:这个后面会详细介绍]:
5. 基本数据类型-字符串类型
- 字符串就是一串固定长度的字符连接起来的字符序列。例: var address string = “北京”
- Go的字符串是由单个字节连接起来的。
- Go语言的字符串的字节使用UTF-8编码标识Unicode文本,这样Golang统一使用UTF-8编码,中文乱码问题不会再困扰程序员。
- 字符串一旦赋值了,字符串就不能修改了:在Go中字符串是不可变的。
- 字符串的两种表示形式:
- 双引号,会识别转义字符
- 反引号(`),以字符串的原生形式输出,包括换行和特殊字符,可以实现防止攻击、输出源代码等效果[案例演示如下]
package main
import "fmt"
// 演示golang中字符串类型的使用
func main() {
// string 的基本使用
var address string = "北京上海 杭州武汉"
fmt.Println(address)
// 字符串一旦赋值了,字符串就不能修改了:在**Go中字符串是不可变的**。
//str[0] = 'a' 不能修改string的内容 cannot assign to str[0]go
var str string = "hello"
fmt.Println(str)
//双引号,会识别转义字符
//反引号,以字符串的原生形式输出,包括换行和特殊字符,可以实现防止攻击、输出源代码等效果[ 案例演示]
str2 := "abc\nabc"
fmt.Println(str2)
str3 := `
package main
import "fmt"
func main() {
//定义变量/声明变量
var i int
// 给 i 赋值
i = 10
// 使用变量
fmt.Println("i=", i)
// +的两种使用
var k, p int
var s1, s2 = "hello", "world"
p = k + i
var s = s1 + s2
fmt.Println("p=", p)
fmt.Println("s=", s)
}
`
fmt.Println(str3)
}
- 字符串的拼接用+
- 如果拼接的字符串很长,可以分行写。加号+一定要保留在上面行
// 字符串的拼接
var str4 string = "world" + "golang"
str4 += "world"
fmt.Println(str4)
//如果拼接的字符串很长,可以分行写。加号+一定要位于上面行
var str5 = "world" + "golang" + "world" + "golang" +"world" + "golang" +
"world" + "golang" + "world" + "golang" + "world" + "golang" +"world" +
"world" + "golang"
fmt.Println(str5)
第三节 Go语言的数据类型转换
1. 基本数据类型默认值
var a int//0
var b float32//0
var c float64//0
var isMarried bool // false
var name string //""
// v表示按照变量的值输出
fmt.Printf("a=%d , b=%f , c=%f,isMarried=%v name=%v" ,a,b,c, isMarried, name)
2. 基本数据类型转换
- Golang和java/c不同,Go在不同类型的变量之间赋值时需要显式转换。也就是说Golang中数据类型不能自动转换。
- 表达式T(v)将值v转换为类型T
- T:就是数据类型,比如int32, int64, float32等等
- v:就是需要转换的变量
- Go中,数据类型的转换可以是从表示范围小- >表示范围大,也可以范围大- ->范围小
- 被转换的是变量存储的数据(即值),变量本身的数据类型并没有变化!(面试中经常被问到)
- 在转换中,比如将int64转成int8,编译时不会报错,只是转换的结果是按溢出处理,和
我们希望的结果不一样。
package main
import "fmt"
// 演示golang中数据类型的转换
func main() {
var i int = 99
// 把i转换为float类型。99.000000类型是:float32,99的数据类型:int
var n1 float32 = float32(i)
fmt.Printf("%f类型是:%T, \n%v的数据类型:%T", n1, n1, i, i)
// 溢出的处理 int64 -> int8。具体溢出的结果不确定,反正想不到的结果
var num int64 = 999998
var num1 int8 = int8(num)
fmt.Println("num1=", num1)
}
3. 基本数据类型转换为string类型
- 在程序开发中,我们经常需要将基本数据类型转成string类型。或者将string类型转成基本数据类型。
- 基本类型转string类型方式一: fmt.Sprintf("%参数", 表达式) [个人习惯这个,灵活]
- 参数需要和表达式的数据类型相匹配
- fmt.Sprintf()…会返回转换后的字符串
- 基本类型转string类型方式二: 使用strconv包的函数
package main
import(
"fmt"
"strconv"
)
// 演示golang中基本数据类型转为string类型
func main() {
var num1 int = 99
var num2 float64 = 23.456
var b bool = true
var myChar byte = 'a'
var str1, str2, str3, str4 string //空的str
//使用第一种方式来转换fmt . Sprintf方法
str1 = fmt.Sprintf("%d", num1)
str2 = fmt.Sprintf("%f", num2)
str3 = fmt.Sprintf("%t", b)
str4 = fmt.Sprintf("%c", myChar)
fmt.Printf("str type %T str=%v\n", str1, str1)
fmt.Printf("str type %T str=%v\n", str2, str2)
fmt.Printf("str type %T str=%v\n", str3, str3)
fmt.Printf("str type %T str=%v\n", str4, str4)
//使用第二种方式来转换fmt。strconv包的函数
str1 = strconv.FormatInt(int64(num1), 10) // 10表示十进制,2表示二进制
str2 = strconv.FormatFloat(num2, 'f', 10, 64) //'f'表示显示格式(10进制或科学技术e),10精度,64表示num2是float64
str3 = strconv.FormatBool(b)
fmt.Printf("str type %T str=%v\n", str1, str1)
fmt.Printf("str type %T str=%v\n", str2, str2)
fmt.Printf("str type %T str=%v\n", str3, str3)
// strconv包中的Itoa非常好用.把int转为string
// %q,加了"" str type string str="1542"
var num5 int = 4567
var str5 string = strconv.Itoa(num5)
var num6 int64 = 1542
var str6 string = strconv.Itoa(int(num6))
fmt.Printf("str type %T str=%v\n", str5, str5)
fmt.Printf("str type %T str=%q\n", str6, str6)
}
4. string类型转换为基本数据类型
- 使用strconv包的函数
- 转换不成功的话,变为默认值。比如:字符串hello 转int。结果为0
package main
import(
"fmt"
"strconv"
)
// 演示golang中string类型转为其他基本数据类型
func main() {
// string类型转为布尔类型
var str string = "true"
var b bool
// 1. strconv.ParseBool(str)函数会返回两个值(value bool, err error)
// 2.因为我只想获取到value bool,不想获取err所以我使用_忽略
b, _ = strconv.ParseBool(str)
fmt.Printf("b type %T b=%v\n", b, b)
// string类型转为整数(默认返回的是int64),如果需要变成int32.转一下
var str2 string = "1234590"
var n1 int64
n1, _ = strconv.ParseInt(str2, 10, 64) //十进制,64位
fmt.Printf("b type %T b=%v\n", n1, n1)
// string类型转为float类型(默认返回的是float64).如果需要变成float32.转一下
var str3 string = "123.456"
var f1 float64
f1, _ = strconv.ParseFloat(str3, 64)
fmt.Printf("f1 type %T f1=%v\n",f1, f1)
//注意:n3 type int64 n3=0
var str4 string = "hello"
var n3 int64
n3, _ = strconv.ParseInt(str4, 10, 64)
fmt.Printf("n3 type %T n3=%v\n" ,n3, n3)
}
- 在将String类型转成基本数据类型时,要确保String类型能够转成有效的数据,比如我们
可以把"123" ,转成一个整数,但是不能把"hello" 转成一个整数, 如果这样做,golang直
接将其转成0
第四节 Go语言的数据类型指针(复杂数据类型)
1. 指针类型的基本使用
- 如何获取基本数据类型中变量的地址? 例子:var num int, 获取num的地址: &num
- 指针类型,变量存的是一个地址,这个地址指向的空间存的才是真正的值比如: var ptr *int = &num
- 获取指针类型所指向的值使用: *,比如: var *ptr int,使用*ptr获取p指向的值
- 注意:指针变量不能给它赋值为普通数据类型,必须是一个(对应类型的)地址。int指针不能赋值float地址
package main
import(
"fmt"
)
// 演示golang中复杂数据类型 指针
func main() {
// 基本数据类型在内存的布局
var i int = 10
// i变量的内存地址是多少呢? &i
fmt.Println("i的内存地址:",&i)
// 下面的 var ptr *int = &i
// 1. ptr是一个指针变量。类型为*int。ptr本身的值是&i
var ptr *int = &i
fmt.Printf("ptr=%v\n", ptr)
// 2. 取出指针存的地址指向的值
fmt.Printf("*ptr指向的值:%v\n", *ptr)
// 3. 通过ptr给i赋值 i的值:20
*ptr = 20
fmt.Printf("i的值:%v\n", i)
}
2. 指针类型的使用细节
- 值类型,都有对应的指针类型,形式为*数据类型,比如int的对应的指针就是 *int, float32 对应的指针类型就是*float32; 依次类推。
- 值类型包括(面试常问):基本数据类型int系列, float 系列, bool, string、 数组和结构体struct
第五节 值类型和引用类型
1. 值类型和引用类型
- 值类型: 基本数据类型int系列, float系列,bool, string、数组和结构体struct
- 引用类型:指针、slice切片、 map、管道chan、interface 等都是引用类型
2. 值类型和引用类型使用特点
- 值类型:变量直接存储值,内存通常在栈中分配。go特点:编译逃逸分析(也可能在堆)
- 引用类型:变量存储的是一个地址,这个地址对应的空间才真正存储数据(值),内存通常在堆上分配,当没有任何变量引用这个地址时,该地址对应的数据空间就成为一个垃圾,由GC来回收。