• Go学习第二章——变量与数据类型


    1 变量

    1.1 变量概念

    变量相当于内存中一个数据存储空间的表示

    1.2 变量的使用步骤

    (1)声明变量(也叫:定义变量)

    (2)非变量赋值

    (3)使用变量

    在这里插入图片描述

    1.3 变量的注意事项

    (1)变量表示内存中的一个存储区域

    (2)该区域有自己的名称(变量名)和类型(数据类型)

    在这里插入图片描述

    (3)Golang变量使用的三种方式

    • 第一种:声明后不赋值,使用默认值,例如:int数据类型默认值为 ‘0’
    func main() {
    	// 声明不赋值,int数据类型默认值为 0
    	var i int
    	fmt.Println("i=", i)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 第二种:根据值自行判断变量类型(类型推导,自动判断)
    func main() {
    	// 根据自行判定变量类型(类型推导,自动判断)
    	var num = 10.11
    	fmt.Println("num=", num)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 第三种:省略var,注意: = 左侧的变量不应该是已经声明过的,否则会导致编译错误
    func main() {
    	// 第三种:省略var,等价于 var name string, name = "tom"
    	num := "tom"
    	fmt.Println("num=", num)
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    (4)多变量声明

    一次性声明多个变量

    func main() {
    	// 对应上面第一种方式
    	var a1, a2, a3 int
    	fmt.Println("a1=", a1, "a2=", a2, "a3=", a3)
    	// 对应上面第二种方式
    	var b1, b2, b3 = 100, "tom", 888
    	fmt.Println("b1=", b1, "b2=", b2, "b3=", b3)
    	// 对应上面第三种方式
    	c1, c2, c3 := 100, "tom", 888
    	fmt.Println("c1=", c1, "c2=", c2, "c3=", c3)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    (5)全局变量的声明

    package main
    
    // 定义全局变量
    var n1 = 100
    var n2 = 200
    var n3 = "Tom"
    
    // 一次性声明
    var (
    	n4 = 300
    	n5 = "Mary"
    )
    
    func main() {
    	// 注意:这里声明的变量和全局变量不能名字重复,
    	// var n1 = 1000
    	// 相当于把全局变量的n1值给修改
    	n1 = 1000
    	println("n1=", n1, "n2=", n2, "n3=", n3, "n4=", n4, "n5=", n5)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    (6)该区域的数据值可以在同一数据类型范围内重复赋值(变化,修改)

    func main() {
    	var i int
    	i = 1
    	i = 2
    	i = 3
    	fmt.Println(i)
    	// i = 1.1 报错:数据类型不同
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    (7)变量在同一个作用域(在一个函数或者在代码块)内不能重名

    func main() {
    	var i int
    	i = 1
    	// var i int 报错:重名
    	// i := 2 报错:同上,因为这个是两个语句的合体
    	fmt.Println("i=", i)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    (8)变量=变量名+值+数据类型,注意这是变量的三要素

    (9)Golang的变量如果没有赋初值,编译器会使用默认值,比如int默认值 0 , string默认值 空串,小数默认值 0

    1.4 "+"的使用
    • 当左右两边都是数值型时,做加法运算
    • 当左右两边都是字符串时,做字符串拼接
    func main() {
    	var a, b = 1, 2
    	fmt.Println("a+b=", a+b)
    	var n1, n2 = "你", "好"
    	fmt.Println("n1+n2=", n1+n2)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2 数据类型介绍

    每一种数据都定义了明确的数据类型,在内存中分配了不同大小的内存空间

    下面是主要和常用的数据类型

    不过少了rune(int32的别名,表示一个Unicode码,处理带中文的字符串)和complex64,128(复数数据类型)

    在这里插入图片描述

    区别于java,不使用short等来区分内存空间大小,例如:int8 占用8位,也就是1个byte

    注意:

    1. 没有字符型char这种数据类型,使用byte存储时,只能存字母,不能存单个汉字

    2. string 在go语言属于基本数据类型

    3 整数类型

    简单的说,就是用于存放整数值的,比如10,-45,6712等等。

    3.1 有符号整数类型

    在这里插入图片描述

    PS:127怎么算出来的?

    01111111 -->二进制 —》转为十进制:
    12^6 + 12^5 + 12^4 + 12^3 + 12^2 + 12^1 + 1*2^0
    = 64 + 32 + 16 + 8 + 4 + 2 + 1
    = 127

    PS:-128怎么算出来的?
    10000000 —>二进制 —>一看就是个负数

    进行负数的二进制计算

    减1:01111111
    取反:10000000 —》得到一个正数 2^7 = 128
    加负号:-128

    3.2 无符号整数类型

    在这里插入图片描述

    表数范围的边界计算:
    11111111= 2^7+127 = 128 + 127 = 255
    00000000 = 0

    3.3 其他整数类型

    在这里插入图片描述

    3.4 整型的使用细节
    1. Golang各整数类型分为:有符号和无符号,int uint 的大小和系统有关

    2. Golang的整数类型,默认声明为int类型

    func main() {
    	var a = 1
    	// fmt.Printf()可以用于做格式化输出
    	fmt.Printf("a 的数据类型:%T", a)
        // 输出:a 的数据类型:int
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. 如何在程序查看某个遍历的占用字节大小和数据类型(使用较多)
    func main() {
    	var n1 byte = 10
    	// fmt.Printf()可以用于做格式化输出
    	// unsafe.Sizeof(a) 是unsafe包的一个函数,可以返回n1变量占用的字节数
    	fmt.Printf("n1 的数据类型:%T ,n1占用的字节数是 %d ", n1, unsafe.Sizeof(n1))
        // 输出:n1 的数据类型:uint8 ,n1占用的字节数是 1
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    1. Golang程序中整型变量在使用时,遵守保小不保大的原则,即:在保证程序正确运行下,尽量使用占用空间小的数据类型。如:年龄,可以使用byte,就占用一个字节
    2. bit:计算机中的最小存储单位。byte:计算机中基本存储单元。一个byte = 8bit

    4 小数类型/浮点型

    简单的说,就是用于存放小数值的,比如3.14、0.28、-7.19等等。

    4.1 浮点型的分类

    在这里插入图片描述

    PS: 底层存储空间和操作系统无关
    PS:浮点类型底层存储:符号位+指数位+尾数位,所以尾数位只是存了 一个大概,很可能会出现精度的损失。

    4.2 简单使用
    func main() {
    	num1 := 5.12
    	num2 := 0.12
        // 科学计数法的使用
    	num3 := 5.1234e2 // 5.1234 * 10的2次方
    	fmt.Println("num1=", num1, "num2=", num2, "num3=", num3)
    	// 输出:num1= 5.12 num2= 0.12 num3= 512.34
    	fmt.Printf("num3的数据类型: %T", num3)
    	// 输出:num3的数据类型: float64
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    注意:推荐使用float64

    5 字符类型

    5.1 字符类型的使用
    1. Golang中没有专门的字符类型,如果要存储单个字符(字母),一般使用byte来保存。
    2. Golang中字符使用UTF-8编码
    func main() {
    	var a byte = 'a'
    	var b byte = '0'
    	fmt.Println("a = ", a, ",b = ", b)
    	// 输出:a =  97 ,b =  48
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    ASCII码表:
    左面是不可见字符 右面是可见字符

    在这里插入图片描述

    1. 如果我们需要输出对应字符,需要使用格式化输出
    func main() {
        var a byte = 'a'
        var b byte = '0'
        fmt.Printf("a = %c ,b = %c", a, b)
        // 输出:a = a ,b = 0
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. 输出汉字的方式
    func main() {
        //var a byte = '北' // overflow溢出
        var a int = '北'
        fmt.Printf("a=%c,a对应码值=%d", a, a)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    5.2 转义字符

    \转义字符:将后面的字母表示为特殊含义

    在这里插入图片描述

    5.3 字符使用的注意事项
    1. 字符常量是用单引号''括起来的单个字符
    2. Go语言的字符使用UTF-8编码 英文字母1个字节,汉字3个字节
    3. 字符的本质是一个整数,直接输出时,是该字符对应的UTF-8编码码值
    4. 格式化输出%C,会输出该数字对应的unicode字符
    5. 字符类型是可以进行运算的,相当于一个整数,因为它都对应有Unicode

    PS:字符型 存储到 计算机中

    • 存储:字符 -> 对应码值 -> 二进制 -> 存储
    • 读取:二进制 -> 码值 -> 字符 -> 读取

    PS:GO语言的编码都统一成了utf-8。非常的方便,很统一,再也没有编码乱码的困扰了。

    6 布尔类型

    1. 布尔类型也叫bool类型,bool类型数据只允许取值truefalse
    2. 布尔类型占1个字节。
    3. 布尔类型适于逻辑运算,一般用于程序流程控制
    func main() {
    	var n = false // 不允许使用 0,1
    	fmt.Println("n =", n)
    }
    
    • 1
    • 2
    • 3
    • 4

    7 字符串类型

    7.1 基本使用

    字符串就是一串固定长度的字符连接起来的字符序列。

    func main() {
        var address string = "北京长城 110 hello world"
        fmt.Println("address = " + address)
        // 输出:address = 北京长城 110 hello world
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    7.2 string使用注意事项
    1. Go的字符串是由单个字节连接起来的。Go语言的字符串的字节使用UTF-8编码标识Unicode文本,这样Golang统一使用UTF-8编码,中文乱码问题不会再困扰程序员。
    2. 字符串一单赋值了,字符串就不能修改了:在Go中字符串是不可变的
    func main() {
        var address string = "北京长城 110 hello world"
        // address[0] = '哈' // 报错!不能修改!
        fmt.Println("address = ", address)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1. 字符串的两种表示形式
    • 双引号,会识别转义字符
    • 反引号,以字符串的原生形式输出,包括换行和特殊字符,可以实现防止攻击、输出源代码等效果

    8 基本数据类型的转换

    8.1 基本使用

    Go在不同类型的变量之间赋值时需要显式转换,并且只有显式转换(强制转换)

    语法:
    表达式T(v)将值v转换为类型T
    T : 就是数据类型
    v : 就是需要转换的变量

    func main() {
        var n1 int32 = 100
        // var n2 float32 = n1 报错
        var n2 float32 = float32(n1)
        fmt.Printf("n1 = %v n2 = %v ", n1, n2)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    **注意:**转换的结果如果超出范围,就会按照溢出处理,不会编译错误,只是会和我们希望的结果不一样。

    8.2 基本数据类型转化为string类型

    在程序开发中,我们经常需要将基本数据类型转成string类型。或者将string类型转成基本数据类型。
    基本类型转string类型的两种方式
    方式1:fmt.Sprintf(“%参数”,表达式) —》 重点练习这个,推荐方式
    方式2:使用strconv包的函数

    方式1 代码演示:

    import "fmt"
    
    func main() {
        var num1 int = 99
        var str1 string = fmt.Sprintf("%d", num1)
        fmt.Printf("str1 type:%T, str1 = %v", str1, str1)
    
        fmt.Println()
    
        var num2 float64 = 23.456
        str2 := fmt.Sprintf("%f", num2)
        fmt.Printf("str2 type:%T, str2 = %v", str2, str2)
    
        fmt.Println()
    
        var b bool = true
        str3 := fmt.Sprintf("%t", b)
        fmt.Printf("str3 type:%T, str3 = %v", str3, str3)
    
        fmt.Println()
    
        var myChar byte = 'h'
        str4 := fmt.Sprintf("%b", myChar)
        fmt.Printf("str4 type:%T, str4 = %v", str4, str4)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    输出:

    str1 type:string, str1 = 99
    str2 type:string, str2 = 23.456000
    str3 type:string, str3 = true
    str4 type:string, str4 = 1101000
    
    • 1
    • 2
    • 3
    • 4

    方式2 代码演示:

    func main() {
        var num1 int = 99
        // 表示10进制
    	str1 := strconv.FormatInt(int64(num1), 10) 
    	// str1 := strconv.Itoa(num1) 同上
    	fmt.Printf("str1 type:%T, str1 = %v\n", str1, str1)
    
        var num2 float64 = 23.456
        // 'f' 格式 10:表示小数位保留10位 64 表示是float64
        str2 := strconv.FormatFloat(num2, 'f', 10, 64) 
        fmt.Printf("str2 type:%T, str2 = %v\n", str2, str2)
    
        var b bool = true
        str3 := strconv.FormatBool(b)
        fmt.Printf("str3 type:%T, str3 = %v\n", str3, str3)
    
        var myChar byte = 'h'
        // str4 := strconv.FormatInt(int64(myChar), 2)
        str4 := string(myChar)
        fmt.Printf("str4 type:%T, str4 = %v\n", str4, str4)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    输出:

    str1 type:string, str1 = 99
    str2 type:string, str2 = 23.456000
    str3 type:string, str3 = true
    str4 type:string, str4 = h
    
    • 1
    • 2
    • 3
    • 4
    8.3 string类型转化为基本数据类型
    func main() {
        // 说明:num1, _ := strconv.ParseInt() 表示忽略第二个函数的返回值,使用下划线"_"
    
        str1 := "99"
        // num1, _ := strconv.Atoi(str1) // 与下面这个相同
        num1, _ := strconv.ParseInt(str1, 10, 64) // 只能转化为int64,但是不能为int类型,int类型只能用上面这个
        fmt.Printf("num1 type:%T, num1 = %v\n", num1, num1)
    
        str2 := "23.456"
        num2, _ := strconv.ParseFloat(str2, 64)
        fmt.Printf("num2 type:%T, num2 = %v\n", num2, num2)
    
        str3 := "true"
        b, _ := strconv.ParseBool(str3)
        fmt.Printf("b type:%T, b = %v\n", b, b)
    
        str4 := "h"
    	// myChar2 := str4[0] 结果与下面这个相同
    	myChar := byte(str4[0])
    	fmt.Printf("myChar type:%T, myChar = %v\n", myChar, myChar)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    输出为:

    num1 type:int64, num1 = 99
    num2 type:float64, num2 = 23.456
    b type:bool, b = true
    myChar type:uint8, myChar = 104
    
    • 1
    • 2
    • 3
    • 4

    注意事项:

    确保转换之间的数据类型没有问题,不然Golang不会报错,但是数据是当前数据类型的默认值

    可以把“123”转为一个整数,但不能把“hello”转成一个整数,如果这样做,Golang直接将其转成默认值 0

    例子:

    func main() {
        var str string = "hello"
        var num int64
        num, _ = strconv.ParseInt(str, 10, 64)
        fmt.Printf("num type = %T, num value = %d \n", num, num)
        // 输出为:num type = int64, num value = 0
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    9指针

    9.1 基本介绍
    1. 基本数据类型,变量存的就是值,也叫值类型
    2. 获取变量的地址,用&,比如:var num int,获取num的地址:&num
    3. 指针类型,指针变量存的是一个地址,这个地址指向的空间存的才是值,比如:var ptr *int = &num
    4. 获取指针类型所指向的值,使用:*,比如:var *ptr int,使用 *ptr获取p指向的值
    9.2 指针使用

    获取a的内存地址:&a

    存储一个遍历的内存地址:var b *int = &a

    func main() {
        var a int = 60
        fmt.Println("a的内存地址:", &a)
    
        // b存储a的内存地址,自己也是有属于自己的内存地址
        var b *int = &a
        fmt.Println("b存储的值:  ", b) // 也就是内存地址
        fmt.Println("b的内存地址:", &b)
    
        //想获取b这个指针或者这个地址指向的那个数据:
        fmt.Println("b指向的数值为:", *b)
        fmt.Printf("b指向的数值为: %v", *b)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    输出:

    a的内存地址: 0xa00a0b8
    b存储的值:   0xa00a0b8
    b的内存地址: 0xa022058
    b指向的数值为: 60     
    b指向的数值为: 60  
    
    • 1
    • 2
    • 3
    • 4
    • 5

    内存地址的展示:

    在这里插入图片描述

    9.3 使用注意事项

    修改存储内存地址变量对应的值

    将num的地址赋给指针ptr,并通过ptr去修改num的值

    func main() {
        var num int = 300
        fmt.Println("num的内存地址:", &num)
        fmt.Println("num的值为:", num)
    
        var ptr *int = &num
        // 这里直接修改了num的值
        *ptr = 200
        fmt.Println("num的值为:", num)
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    输出:

    num的内存地址: 0x980a0b8
    num的值为: 300
    num的值为: 200
    
    • 1
    • 2
    • 3
    9.4 值类型和引用类型

    Go语言中的值类型和引用类型是对变量的分类方式。这两种类型之间的主要区别在于变量的赋值和传递时的行为。

    **值类型:**包括基本数据类型(如整型、浮点型、布尔型等)以及结构体(struct)和数组(array)。

    默认存在中的

    当我们将一个值类型的变量赋值给另一个变量时,会将该值进行拷贝,修改其中一个变量的值不会影响到另一个变量。同样,将这些值类型的变量作为函数的参数传递时,也是按值传递的,即传递的是值的拷贝。

    **引用类型:**包括指针(pointer)、切片(slice)、映射(map)、接口(interface)、通道(channel)以及函数(function)。

    默认存在中,除了字符串类型(string),存在栈中。当没有任何变量引用这个地址时,该地址的数据空间就成为一个垃圾,由GC(垃圾回收)来回收。

    当我们将一个引用类型的变量赋值给另一个变量时,会将指向同一内存地址的指针进行拷贝,修改其中一个变量的值会影响到另一个变量。引用类型的变量在进行函数参数传递时,传递的是该变量指针的拷贝,修改变量值也会影响到原始变量。

    区分值类型和引用类型对于理解变量的赋值和传递行为非常重要。

    值类型操作简单高效,每个变量都拥有自己的独立副本

    引用类型则允许通过共享内存来节省内存和复制开销,但需要注意对共享数据的并发访问问题

    注意:字符串类型(string)也是引用类型,但它在底层的实现上由字节数组组成,所以在赋值和传递时与值类型的行为类似。

    10 标识符

    10.1 基本使用

    变量,方法等,只要是起名字的地方,那个名字就是标识符 var age int = 19 var price float64 = 9.8

    标识符定义规则:

    1. 三个可以(组成部分):数字,字母,下划线_

    2. 四个注意:不可以以数字开头,严格区分大小写,不能包含空格,不可以使用Go中的保留关键字(break,if等)

    3. 见名知意:增加可读性

    4. 下划线"_"本身在Go中是一个特殊的标识符,称为空标识符。可以代表任何其它的标识符,但是它对应的值会被忽略(比如:忽略某个返回值)。所以仅能被作为占位符使用,不能单独作为标识符使用。

    标识符的命名规范

    1. 包名:尽量保持package的名字和目录保持一致,尽量采取有意义的包名,简短,有意义,和标准库不要冲突

    2. 变量名、函数名、常量名 : 采用驼峰法。

    3. 如果变量名、函数名、常量名首字母大写,则可以被其他的包访问;(public共有的
      如果首字母小写,则只能在本包中使用 (利用首字母大写小写完成权限控制)(private私有的

    10.2 导包和标识符的使用

    第一步:创建一个文件夹demo,再创建一个文件夹model,创建一个go文件,随便写个变量

    在这里插入图片描述

    第二步:在test.go里调用包的使用

    在这里插入图片描述

    **注意:**如果model里的变量名为heroName,就不能被导包后调用,因为是私有的,需要改成大写HeroName

    import导入语句通常放在文件开头包声明语句的下面。
    导入的包名需要使用双引号包裹起来。
    包名是从$GOPATH/src/后开始计算的,使用/进行路径分隔。

    $GOPATH是环境遍历最开始的时候配置的,记得要去配置~~~

    10.3 保留关键字和预定义标识符

    在这里插入图片描述

    over!!!!!第二章学习结束!! 主要是关于,变量和数据类型~~~

  • 相关阅读:
    微信小程序 ---- 慕尚花坊 收货地址
    Vue模块语法下(事件处理器&自定义组件&组件通信)
    100.一个linux内核选项对ssh的影响
    Android使用AtomicReference
    2流高手速成记(之三):SpringBoot整合mybatis/mybatis-plus实现数据持久化
    会议AISTATS(Artificial Intelligence and Statistics) Latex模板参考文献引用问题
    基于springboot框架的校园食堂外卖点餐系统
    【洛谷P1225】黑白棋游戏【DFS】【状压】
    教育培训机构寒暑假班学校公众号小程序
    仿热血江湖游戏类46物品消失
  • 原文地址:https://blog.csdn.net/Hai_Helloyou/article/details/133936695