Go学习笔记(篇三)数据类型

Golang.png

数据类型

Go语言内置以下这些类型:

表3-1 Go语言支持的数据类型
基础类型关键字复合类型
布尔类型bool指针(pointer)
整形int8、byte、int16、unit、uintptr数组(array)
浮点类型float32、float64切片(slice)
复数类型complex64、complex128字典(map)
字符串string通道(chan)
字符类型rune结构体(struct)
错误类型error接口(interface)

1 布尔类型

布尔类型不能接受其他类型的赋值,不支持自动或强制的类型转换。以下是bool类型的用法示例:

表3-2 bool类型的使用示例
正确用法错误用法
var b bool
b = (1!=0)
fmt.Println("Result:",b)   //打印结果为Result:true
var b bool
b = 1  //错误编译
b = bool(1)   //错误编译

2 整形

整形是所有编程语言里最基础的数据类型。Go语言支持的整形类型如下表所示:

表3-3 Go语言支持的整形类型
类型长度(字节)值范围
int81

-128 ~ 127

uint8(即byte)1

0 ~ 225

int162

-32 768 ~ 32 767

uint162

0 ~ 65 535

int324

-2 147 483 648 ~ 2 147 483 647

uint324

0 ~ 4 294 967 295

int648

-9 223 372 036 854 775 808 ~ 9 223 372 036 854 775 807

int平台相关

平台相关

uint平台相关

平台相关

uintptr同指针

在32位平台下为4字节,64位平台下为8字节

2.1 类型表示

int和int32在Go语言里被认为是两种不同的类型,编译器不会自动做类型转换,使用强制类型转换可以解决这个问题,但要注意数据损失和溢出的问题(在这里不做具体分析),样例如下:

表3-4 int类型表示用法 
正确用法错误用法
var v1 int32
v2 := 64
v1 = int32(v2) //编译正确
var v1 int32
v2 := 64
v1 = v2 //编译错误

2.2 数值运算

表3-5 Go语言支持的数值运算
符号功能例子
+加法运算6 + 3  =   9
-减法运算6 - 3  =   3
*乘法运算6 * 3  = 18
/除法运算6 / 3  =   2
%取余运算6 % 3 =   0

2.3 比较运算

Go语言支持以下的几种比较运算符:>、<、==、>=、<=和!=。和大多数其他编程语言相同,在这里就不做具体说明了。(需要注意的是不同类型的整形数不能直接比较,但可以直接与字面常量进行比较)

2.4 位运算

Go语言支持表3-6所示的运算符。

表3-6 Go语言支持的运算符
运算含义样例
x << y
左移124 << 2   //结果为496
x >> y右移124 >> 2   //结果为31
x ^ y异或124 ^ 2     //结果为126
x & y124 & 2    //结果为0
x | y124 | 2      //结果为126
^x取反^124        //结果为-125

3 浮点型

浮点型用于表示包含小数点的数据,比如1.234就是一个浮点型数据。Go语言中的浮点类型采用IEEE-754标准的表达方式。

3.1 浮点数表示

Go语言定义了两个类型float32和float64,分别等价于C语言的float类型和double类型,样例如下:

var fvalue1 float 32
fvalue1 = 12
fvalue2 := 12.0 //如果不加小数点,fvalue2会被推导为整形
fvalue3 := float32(fvalue2) //必须使用强制类型转换,直接赋值将导致编译错误

3.2 浮点数比较

因为浮点数不是一种精确的表达方式,所以直接使用“==”来判断两个浮点数是否相等会导致不稳定的结果。下面是一种推荐的替代方案:

import "math"

4 复数类型

复数实际上由两个实数(在计算机中用浮点数表示)构成,一个表示实部(real),一个表示虚部(imag)。样例如下:

package main //必须有一个main包
 
import "fmt"
 
func main() {
    var cvalue1 complex128 //声明
    cvalue1  = 2.1 + 3.14i  //赋值
    fmt.Println("cvalue1  = ", cvalue1 )
 
    //自动推导类型
    cvalue2 := 3.3 + 4.4i
    fmt.Printf("cvalue2 type is %T\n", cvalue2)
 
    //通过内建函数,取实部和虚部
    fmt.Println("real(cvalue2) = ", real(cvalue2), ", imag(cvalue2) = ", imag(cvalue2))
 
}

5 字符串

在Go语言中,字符串也是一种基本类型。相比之下,C/C++语言并不存在原生的字符串类型,通常使用字符数组来表示,并以字符指针来传递。字符串的声明和使用的样例如下:

package main

import "fmt"

func main() {
   var str string
   str = "Hello world"
   fmt.Println(str)
}

字符串的内容可以用类似于数组下标的方式获取,但与数组不同,字符串的内容不能在初始化后被修改。

5.1 字符串操作

平时常用的字符串操作如表3-7所示。

表3-7 字符串操作方法对照表
运算含义样例
x + y字符串连接"Hello" + "World"     // 结果为HelloWorld

len(str)

字符串长度len("HelloWorld")    // 结果为10              
s[i]取字符"HelloWorld"[1]        // 结果为'e'                 

5.2 字符串遍历

Go语言支持两种方式遍历字符串,样例如下表所示:

表3-8 字符串变量方法表
字节数组遍历
Unicode字节遍历
package main

import "fmt"

func main() {
   str := "Hello,世界"
   n := len(str)
   for i := 0 ; i < n ; i++ {
      fmt.Println(i, str[i])
   }
}
/* 运行结果
0 72
1 101
2 108
3 108
4 111
5 44
6 228
7 184
8 150
9 231
10 149
11 140
*/
package main

import "fmt"

func main() {
   str := "Hello,世界"
   for i , ch := range str{
      fmt.Println(i, ch)
   }
}

/* 运行结果
0 72
1 101
2 108
3 108
4 111
5 44
6 19990
9 30028
*/

6 字符类型

在Go语言中支持两种字符类型,一个是byte(实际上是unit8的别名),代表UTF-8字符串的单个字节的值;另一个是rune,代表单个Unicode字符。

7 数组

数组是Go语言编程中最常用的数据结构之一。顾名思义,数组就是指一系列同一类型数据的集合。数组中包含的每个数据被称为数组元素(element),一个数组包含的元素个数被称为数组的长度。以下为一些常规的数组声明方法:

var b [32]byte          //长度为32的数组,每个元素为一个字节
var s [32] struct{x,y int}   //复杂类型数组
var f1 [32] *float64       //指针数组
var f2 [2][4][4] float64     //等同于[2]([2]([2] float64))
var i [4][8] int         //二维数组

8 数组切片

数组的长度在定义之后无法再次修改;数组是值类型,每次传递都将产生一份副本。这些都是数组的特点,但这种数据结构无法完全满足开发者的真实需求。Go语言提供了数组切片(slice)这种数据类型来弥补数组的不足。

数字切片就像一个指向数组的指针,数组切片的数据结构可以抽象为以下3个变量:

  • 一个指向原生数组的指针;

  • 数组切片中的元素个数;

  • 数组切片已分配的存储空间。

QQ图片20220725163350.png

8.1 创建数组切片

创建数组切片的方法如下表所示:



基于数组
package main

import "fmt"

func main() {
   //定义数组
   var array [10]int = [10]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

   //基于前五个数组元素创建一个切片
   var slice []int = array[:5]
   //从第五个数组元素创建一个切片   array[5:]
   //数组转为切片 array[:]
   fmt.Println("Array:")
   for _, v := range array {
      fmt.Print(v, " ")
   }
   fmt.Println("")
   fmt.Println("Slice:")
   for _, v := range slice {
      fmt.Print(v, " ")
   }
}
//运行结果为:
//Array:
//0 1 2 3 4 5 6 7 8 9 
//Slice:              
//0 1 2 3 4


直接创建
package main

import "fmt"

func main() {
   //使用make()直接创建数组切片
   //创建一个初始元素个数为5的数组切片,元素初始值为0
   slice1 := make([]int, 5)
   fmt.Println(len(slice1))
   //创建一个初始元素个数为5的数组切片,元素初始值为0,并预留10个元素的存储空间
   slice2 := make([]int, 5, 10)
   fmt.Println(len(slice2))
   //直接创建并初始化包含5个元素的数组切片
   slice3 := []int{0, 1, 2, 3, 4}
   fmt.Println(len(slice3))
}
//运行结果为:
//5
//5
//5


8.2 切片常用的方法

8.2.1 遍历

操作数组元素的所有方法都适用于数组切片,比如数组切片也可以按下标读写元素,用len()函数获取元素的个数,并支持使用range关键字来快速遍历所有元素。

传统的元素遍历如下:

slice := []int{1, 2, 3, 4, 5}
for i := 0; i < len(slice ); i++ {
   fmt.Print(slice [i], " ")
}

使用range关键字可以让遍历代码显得更整洁。range表达式有两个返回值,第一个是索引,第二个是元素的值,代码如下:

slice := []int{1, 2, 3, 4, 5}
for i, v := range slice {
   fmt.Println("d[", i, "]=", v)
}

8.2.2 增减元素

使用append()操作切片,代码如下:

package main

import "fmt"

func main() {
   a := []int{1, 2, 3, 4, 5}
   fmt.Println("a =", a, "len=", len(a))
   d := make([]int, 0)
   //添加切片a的前2个元素,添加切片a下标从3开始之后的元素
   //总结一下:冒号在前是个数;冒号在后是下标,保留的是冒号没有数字的一侧
   //只有(int):和:(int)的用法。
   //添加一个切片要用...展开运算符
   d = append(a[:2], a[3:]...)
   fmt.Println("d =", d, "len=", len(d))
}
//删除切片中的第三个元素
//打印结果如下:
//a = [1 2 3 4 5] len= 5
//d = [1 2 4 5] len= 4

8.2.3 扩容

package main

import "fmt"

func main() {
   a := make([]int, 0)

   fmt.Printf("当前切片的长度:%d,容量:%d\n", len(a), cap(a))

   for i := 0; i < 10; i++ {
      a = append(a, i)
      fmt.Printf("当前切片的长度:%d,容量:%d\n", len(a), cap(a))
   }
}
//打印结果如下:
//当前切片的长度:0,容量:0
//当前切片的长度:1,容量:1  
//当前切片的长度:2,容量:2  
//当前切片的长度:3,容量:4  
//当前切片的长度:4,容量:4  
//当前切片的长度:5,容量:8  
//当前切片的长度:6,容量:8  
//当前切片的长度:7,容量:8  
//当前切片的长度:8,容量:8  
//在添加元素之前判断切片是否有剩余,如果没有剩余且容量小于1024,成倍增加容量
//在没有添加元素之前的容量是8,所以扩容量为8
//当前切片的长度:9,容量:16 
//当前切片的长度:10,容量:16
  • 如果容量小于1024的时候,是成倍数的添加容量

  • 如果容量大于1024的时候,是之前的1/4的来添加容量

9 map

Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。

Map 是一种集合,所以我们可以像迭代数组和切片那样迭代它。不过,Map 是无序的,我们无法决定它的返回顺序,这是因为 Map 是使用 hash 表来实现的。

9.1 map的常见用法

package main

import "fmt"

type StudentInfo struct {
   Name      string
   ClassRoom string
}

func main() {
   var students map[int]StudentInfo
   students = make(map[int]StudentInfo)

   //添加元素
   students[0] = StudentInfo{"小明", "三年级(1)班"}
   students[1] = StudentInfo{"小红", "三年级(1)班"}
   students[2] = StudentInfo{"小李", "三年级(2)班"}
   students[3] = StudentInfo{"小王", "三年级(2)班"}
   students[4] = StudentInfo{"小赵", "三年级(3)班"}

   //遍历元素
   fmt.Println("学生信息如下:")
   for _, student := range students {
      fmt.Println(student)
   }

   //查找元素
   stua, ok := students[3]
   if ok {
      fmt.Println("下标是3的学生信息:", stua)
   } else {
      fmt.Println("查找失败!")
   }

   //删除元素
   delete(students, 1)
   fmt.Println("新的学生信息如下:")
   for _, student := range students {
      fmt.Println(student)
   }

   //修改元素
   stub, ok := students[2]
   if ok {
      stub.ClassRoom = "三年级(3)班"
   } else {
      fmt.Println("查找失败!")
   }
   fmt.Println("修改后的学生信息:", stub)

}

参考:

  1. 总结go语言中切片的使用_水痕01的博客-CSDN博客_go语言切片的三种方法

  2. Go 切片详解(理解是关键) | Go 技术论坛 (learnku.com)

  3. Go 语言Map(集合) | 菜鸟教程 (runoob.com)



#转载请注明出处!
快来制作你的简历吧 ,请猛戳这里→点击在线制作
宝塔服务器面板,一键全能部署及管理,送你3188元礼包。请猛戳这里→点我领取

本文标题:《Go学习笔记(篇三)数据类型》作者:xuanzhe
原文链接:https://blog.xuanzhe.club/?id=62
特别注明外均为原创,转载请注明。

分享到微信

扫描二维码

可在微信查看或分享至朋友圈。

相关文章

发表评论:
验证码

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

你好,朋友

真是美好的一天!

访客信息

  • IP: 3.144.187.103
  • 地点: United StatesOhioDublin

标签列表

站点信息

  • 文章总数:69
  • 页面总数:2
  • 分类总数:19
  • 标签总数:34
  • 评论总数:7
  • 浏览总数:147010
您好,欢迎到访网站!
忘记密码

网站分类

文章归档

歌曲 - 歌手
0:00