当前位置:网站首页>(三)Golang - 数据类型
(三)Golang - 数据类型
2022-06-12 16:43:00 【二进制杯莫停】
Golang 数据类型
1 基础数据类型
1.1 分类
类型 | 名称 | 长度 | 零值 | 说明 |
---|---|---|---|---|
bool | 布尔类型 | 1 | false | 其值不为真则为假,不可用数字代替true或false |
byte | 字节类型 | 1 | 0 | uint8别名 |
rune | 字符类型 | 4 | 0 | 专用于存储unicode编码,等价于int32 |
int,uint | 整型 | 4或8 | 0 | 32位或64位 |
int8,uint8 | 整型 | 1 | 0 | -128 ~ 127, 0 ~ 255 |
int16,uint16 | 整型 | 2 | 0 | -32768 ~ 32767, 0 ~ 65535 |
int32,uint32 | 整型 | 4 | 0 | -21亿 ~ 21亿, 0 ~ 42亿 |
int64,uint64 | 整型 | 8 | 0 | |
float32 | 浮点型 | 4 | 0.0 | 小数位精确到7位 |
float64 | 浮点型 | 8 | 0.0 | 小数位精确到15位 |
complex64 | 复数类型 | 8 | ||
complex128 | 复数类型 | 16 | ||
uintptr | 整型 | 4或8 | 足以存储指针的uint32或uint64整数 | |
string | 字符串 | "" | utf-8字符串 |
int和uint(有符号整数 / 无符号整数):根据底层平台,表示32位或者65位整数。除非使用非常大的整数,否则通常使用int来表示整数。
1.1.1 类型应用
// 布尔类型
var b bool = false
// 整型
var i int = 10
// 浮点型
var f float = 3.14
f2 := 12.0
1.1.2 字符串型
概念:多个byte的集合,理解为一个字符序列
语法:使用""
或使用``
//1. 定义字符串
var s1 string
s1 = "张三"
fmt.Printf("%T,%s\n", s1, s1)
s2 := `hello world`
fmt.Printf("%T,%s\n", s2, s2)
字符A和字符串A的区别
:
package main
import "fmt"
func main(){
//2. 区别'A', "A"
v1 := 'A'
v2 := "A"
fmt.Printf("%T, %d\n", v1, v1)
fmt.Printf("%T, %s\n", v2, v2)
v3 := '中'
fmt.Printf("%T, %d, %c, %q\n", v3, v3, v3, v3)
}
控制台输出:
$ go run xxx.go
int32, 65
string, A
int32, 20013, 中, '中'
1.1.3 数据类型转换
语法格式:Type(Value)
常数:在有需要的时候自动转型
变量:需要手动转型T(V)
注意点:兼容类型可以互相转换
package main
import "fmt"
func main(){
var a int8
a = 10
var b int16
b = int16(a)
fmt.Println("a = ", a)
fmt.Println("b = ", b)
f1 := 4.83
var c int
c = int(f1)
fmt.Println("c = ", c)
}
控制台输出:
$ go run xxx.go
a = 10
b = 10
c = 4
2 复合数据类型
包括:
- 指针类型(Pointer)
- 数组类型
- 结构化类型(struct)
- Channel 类型
- 函数类型
- 切片类型
- 接口类型(interface)
- Map 类型
2.1 数组(Array)
Go语言提供了数组类型的数据结构。
数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,这种类型可以是任意的原始类型例如整型、字符串或者自定义类型。
数组元素可以通过索引(位置)来读取(或者修改),索引从0开始,第一个元素索引为0。
数组一旦定义后,大小不能更改。
2.1.1 数组的语法
声明和初始化数组
需要知名数组的大小和存储的数据类型。
variable_name [SIZE] variable_type
示例代码:
package main
import "fmt"
func main() {
//1. 创建数组
var arr1 [5]int
arr1[0] = 1
arr1[1] = 2
arr1[2] = 3
arr1[3] = 4
arr1[4] = 5
fmt.Println("arr1的长度是:", len(arr1))
fmt.Println("arr1的容量是:", cap(arr1))
}
结果输出:
$ go run xxx.go
arr1的长度是: 5
arr1的容量是: 5
数组其他创建方式:
var a [10]float32
fmt.Println(a)
var b = [5]float32{
1000.0, 2.0, 3.4, 7.0, 50.0}
fmt.Println(b)
var c = [5]int{
1, 2, 4}
fmt.Println(c)
var d = [5]int{
1:1, 3:2}
fmt.Println(d)
var e = []int{
6, 7, 8, 9, 10}
fmt.Println(e)
结果输出:
$ go run xxx.go
[0 0 0 0 0]
[1000 2 3.4 7 50]
[1 2 4 0 0]
[0 1 0 2 0]
[6 7 8 9 10]
2.1.2 数组拷贝是值传递,深拷贝
var e = [5]int{
6, 7, 8, 9, 10}
fmt.Println("e = ", e)
var f [5]int
f = e // 值传递
f[1] = 1
fmt.Println("e = ", e)
fmt.Println("f = ", f)
fmt.Println("f == e ? ", e == f)
var d = [5]int{
1:1, 3:2}
fmt.Println("d = ", d)
g := d // 值传递
g[1] = 2
fmt.Println("d = ", d)
fmt.Println("g = ", g)
fmt.Println("g == d ? ", d == g)
结果输出:
e = [6 7 8 9 10]
e = [6 7 8 9 10]
f = [6 1 8 9 10]
f == e ? false
d = [0 1 0 2 0]
d = [0 1 0 2 0]
g = [0 2 0 2 0]
g == d ? false
2.1.3 多维数组
2.2 切片(slice)
2.2.1 什么是切片
Go语言切片是对数组的抽象。
Go数组的长度不可改变,在特定场景中这样的集合就不太实用,Go中提供了一种灵活,功能强悍的内置类型切片("动态数组"
),与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大
切片与数组相比,不需要设置长度,在[]
中不用设定值,相对来说比较自由
从概念上面来上slice像一个结构体,这个结构体包含了三个元素
:
- 指针,指向数组中slice指定的开始位置
- 长度,即slice的长度
- 最大长度,也就是slice开始位置到数组最后位置的长度
package main
import "fmt"
func main() {
/* 数组array: 存储一组相同数据类型的数据结构 特点:定长 切片slice: 同数组类似,也叫做变长数组或者动态数组 特点:变长 是一个引用类型的容器,指向了一个底层数组 makde() func make(t Type,size ... IntegerType) Type 第一个参数:类型 slice,map,chan 第二个参数:长度len 实际存储元素的数量 第三个参数:容量cap 最多能够存储的元素的数量 */
//1. 数组
arr := [4]int{
1,2,3,4}
fmt.Println(arr)
//2. 切片
var s1 []int
fmt.Println(s1)
s2 := []int{
1,2,3,4}
fmt.Println(s2)
fmt.Printf("arr type is %T,s2 type is %T\n", arr, s2)
s3 := make([]int, 3, 8)
fmt.Println(s3)
fmt.Printf("s3 容量:%d, 长度: %d\n", cap(s3), len(s3))
}
结果输出:
[1 2 3 4]
[]
[1 2 3 4]
arr type is [4]int,s2 type is []int
[0 0 0]
s3 容量:8, 长度: 3
2.2.2 append
两种方法:
slice = append(slice, elem1, elem2)
slice = append(slice, anotherslice...)
实例:
package main
import "fmt"
func main() {
s3 := make([]int, 3, 8)
fmt.Println(s3)
fmt.Printf("s3 容量:%d, 长度: %d\n", cap(s3), len(s3))
s3[0] = 1
s3[1] = 2
s3[2] = 3
fmt.Println(s3)
//fmt.Println(s3[3]) runtime error: index out of range [3] with length 3
//append elem
s4 := make([]int, 0, 5)
fmt.Println(s4)
s4 = append(s4, 1, 2)
fmt.Println(s4)
s4 = append(s4, 3, 4, 5, 6) // 添加超过最大cap的数量
fmt.Println(s4)
//append anotherslice
s4 = append(s4, s3...)
fmt.Println(s4)
}
结果输出:
[0 0 0]
s3 容量:8, 长度: 3
[1 2 3]
[]
[1 2]
[1 2 3 4 5 6]
[1 2 3 4 5 6 1 2 3]
2.2.3 slice自动扩容
/* 切片slice: 1. 每一个切片引用了一个底层数组 2. 切片本身不存在任何数据,都是这个底层数组存储,所以修改切片也就是修改这个数组中的数据 3. 当向切片中添加数据时,如果没有超过容量,直接添加,如果超过容量,自动扩容(原容量 × 2) 4. 切片一旦扩容,就是重新指向了一个新的底层数组 */
s1 := []int{
1, 2, 3}
fmt.Println(s1)
fmt.Printf("len:%d,cap:%d\n", len(s1), cap(s1)) //len:3,cap:3
fmt.Printf("%p\n", s1)
s1 = append(s1, 4, 5)
fmt.Println(s1)
fmt.Printf("len:%d,cap:%d\n", len(s1), cap(s1)) //len:5,cap:6
fmt.Printf("%p\n", s1)
s1 = append(s1, 6, 7, 8)
fmt.Println(s1)
fmt.Printf("len:%d,cap:%d\n", len(s1), cap(s1)) //len:8,cap:12
fmt.Printf("%p\n", s1)
结果输出:
[1 2 3]
len:3,cap:3
0xc0000b6000
[1 2 3 4 5]
len:5,cap:6
0xc0000aa030
[1 2 3 4 5 6 7 8]
len:8,cap:12
0xc00008c060
2.2.4 数组切片初始化
s :=[] int {
1,2,3 }
直接初始化切片,[]
表示是切片类型,{1,2,3} 初始化值依次是 1,2,3,其 cap=len=3
。
s := arr[:]
初始化切片 s,是数组 arr 的引用。
s := arr[startIndex:endIndex]
将 arr 中从下标 startIndex
到 endIndex-1
下的元素创建为一个新的切片。
s := arr[startIndex:]
默认 endIndex 时将表示一直到arr的最后一个元素。
s := arr[:endIndex]
默认 startIndex 时将表示从 arr 的第一个元素开始。
s1 := s[startIndex:endIndex]
通过切片 s
初始化切片 s1。
s :=make([]int,len,cap)
通过内置函数 make()
初始化切片s,[]int
标识为其元素类型为 int 的切片。
2.3 Map
Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。
Map 是一种集合,所以我们可以像迭代数组和切片那样迭代它。不过,Map 是无序的,我们无法决定它的返回顺序,这是因为 Map 是使用 hash 表来实现的。
2.3.1 定义 Map
可以使用内建函数 make 也可以使用 map 关键字来定义 Map:
/* 声明变量,默认 map 是 nil */
var map_variable map[key_data_type]value_data_type
/* 使用 make 函数 */
map_variable := make(map[key_data_type]value_data_type)
示例:
package main
import "fmt"
func main() {
var map1 map[string]int //没有初始化
var map2 = make(map[string]int) //创建
map2["xiaoming"] = 1
var map3 = map[string]int{
"Go":98, "Python":87, "Java":79, "Html":93}
fmt.Println(map1)
fmt.Println(map2)
fmt.Println(map3)
fmt.Println(map1 == nil)
fmt.Println(map2 == nil)
fmt.Println(map3 == nil)
if map1 == nil {
map1 = make(map[string]int)
fmt.Println(map1)
}
}
输出:
map[]
map[xiaoming:1]
map[Go:98 Html:93 Java:79 Python:87]
true
false
false
map[]
2.3.2 Map的使用
package main
import "fmt"
func main() {
//创建
var map1 = make(map[string]int)
//修改数据
map1["xiaoming"] = 18
map1["xiaohong"] = 17
map1["xiaolan"] = 16
fmt.Println(map1)
//删除数据delete
delete(map1,"xiaoming")
fmt.Println(map1)
//长度
fmt.Println(len(map1))
}
结果输出:
map[xiaohong:17 xiaolan:16 xiaoming:18]
map[xiaohong:17 xiaolan:16]
2
2.3.3 Map的遍历
var map1 map[string]int /*创建集合 */
map1 = make(map[string]int)
/* map插入key - value对,各个国家对应的首都 */
map1 [ "France" ] = 1
map1 [ "Italy" ] = 2
map1 [ "Japan" ] = 3
map1 [ "India " ] = 4
/*使用键输出地图值 */
for k, v := range map1 {
fmt.Println(k, "---->", v)
}
for k := range map1 {
fmt.Println(k, "---->", map1[k])
}
结果输出:
France ----> 1
Italy ----> 2
Japan ----> 3
India ----> 4
India ----> 4
France ----> 1
Italy ----> 2
Japan ----> 3
2.3.4 判断key是否存在
判断American是否存在
package main
import "fmt"
func main() {
var map1 map[string]int /*创建集合 */
map1 = make(map[string]int)
/* map插入key - value对,各个国家对应的首都 */
map1 [ "France" ] = 1
map1 [ "Italy" ] = 2
map1 [ "Japan" ] = 3
map1 [ "India " ] = 4
/*查看元素在集合中是否存在 */
capital, ok := map1 [ "American" ] /*如果确定是真实的,则存在,否则不存在 */
/*fmt.Println(capital) */
/*fmt.Println(ok) */
if (ok) {
fmt.Println("American :", capital)
} else {
fmt.Println("American 不存在")
}
}
结果输出:
American 不存在
2.3.5 map结合slice使用
用例:将map中的信息统一打印
package main
import "fmt"
func main() {
//第一个人
map1 := make(map[string]string)
map1["name"] = "王二狗"
map1["age"] = "30"
map1["sex"] = "男性"
map1["address"] = "北京市XX路XX号"
//第二个人
map2 := make(map[string]string)
map2["name"] = "李小花"
map2["age"] = "20"
map2["sex"] = "女性"
map2["address"] = "上海市XX路XX号"
//第三个人
map3 := map[string]string{
"name":"ruby","age":"30","sex":"女性","address":"杭州市"}
//将map存到slice中
s1 := make([]map[string]string, 0, 3)
s1 = append(s1, map1)
s1 = append(s1, map2)
s1 = append(s1, map3)
//便利切片
for i, val := range s1 {
//val: map1, map2, map3
fmt.Printf("第%d个人的信息是:\n", i)
fmt.Printf("\t姓名:%s\n", val["name"])
fmt.Printf("\t年龄:%s\n", val["age"])
fmt.Printf("\t性别:%s\n", val["sex"])
fmt.Printf("\t地址:%s\n", val["address"])
}
}
结果输出:
第0个人的信息是:
姓名:王二狗
年龄:30
性别:男性
地址:北京市XX路XX号
第1个人的信息是:
姓名:李小花
年龄:20
性别:女性
地址:上海市XX路XX号
第2个人的信息是:
姓名:ruby
年龄:30
性别:女性
地址:杭州市
边栏推荐
- WebRTC 的音频网络对抗概述
- 从50亿图文中提取中文跨模态新基准Zero,奇虎360全新预训练框架超越多项SOTA
- 添加静态路由
- 软件工程 学生信息管理系统 结构化的需求分析
- Leetcode 2194. Cellules dans une plage dans un tableau Excel (OK, résolu)
- js 使用Rsa 加密 解密
- Concurrent trichromatic marking
- What is compound interest financial product?
- Recommend AI intelligent drawing repair software
- redis.clients.jedis.exceptions.JedisDataException: NOAUTH Authentication required
猜你喜欢
Google browser debugging skills
About component value transfer
[MySQL] Cartesian product - multi table query (detailed explanation)
redis.clients.jedis.exceptions.JedisDataException: NOAUTH Authentication required
idea如何设置导包不带*号
MySQL interview arrangement
CVPR 2022 | meta learning performance in image regression task
QCustomplot笔记(一)之QCustomplot添加数据以及曲线
Demande de doctorat | xinchao Wang, Université nationale de Singapour
从50亿图文中提取中文跨模态新基准Zero,奇虎360全新预训练框架超越多项SOTA
随机推荐
Preprocessing command section 3
About component value transfer
\Begin{algorithm} notes
1.delete
Three paradigms of database
Leetcode 2194. Excel 表中某个范围内的单元格(可以,已解决)
启牛开的证券账户安全吗?合法吗?
QCustomplot笔记(一)之QCustomplot添加数据以及曲线
Recommend 6 open source projects of yyds
Which colleges are particularly easy to enter?
武汉大学甘菲课题组和南昌大学徐振江课题组联合招聘启事
(六)控制语句if/else switch
js监听用户是否打开屏幕焦点
Leetcode 2194. Excel 錶中某個範圍內的單元格(可以,已解决)
Exception assertion of assertj
Loading shellcode in C and go languages
How to do a good job of testing in the company (do a good job of testing)
Possible problems of long jump in gaussdb
Idea displays services on the console to uniformly manage all jetty services,
PAT甲级 1142 最大团