当前位置:网站首页>(三)Golang - 数据类型

(三)Golang - 数据类型

2022-06-12 16:43:00 二进制杯莫停

1 基础数据类型

1.1 分类

类型名称长度零值说明
bool布尔类型1false其值不为真则为假,不可用数字代替true或false
byte字节类型10uint8别名
rune字符类型40专用于存储unicode编码,等价于int32
int,uint整型4或8032位或64位
int8,uint8整型10-128 ~ 127, 0 ~ 255
int16,uint16整型20-32768 ~ 32767, 0 ~ 65535
int32,uint32整型40-21亿 ~ 21亿, 0 ~ 42亿
int64,uint64整型80
float32浮点型40.0小数位精确到7位
float64浮点型80.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 中从下标 startIndexendIndex-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
	性别:女性
	地址:杭州市
原网站

版权声明
本文为[二进制杯莫停]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_43999327/article/details/125123987