您现在的位置是:网站首页> 编程资料编程资料
Go语言中的复合类型详细介绍_Golang_
2023-05-26
384人已围观
简介 Go语言中的复合类型详细介绍_Golang_
golang复合类型包括:结构体、数组、切片、Maps。
1、数组
数组
golang中的数组与C语言中的数组差异很大,倒更类似Pascal中的数组。 (Slice,下个话题,有些像C语言中的数组)
var ar [3]int
声明ar为一个拥有三个整型数的数组,所有元素初始化为0。
大小是类型的一个组成部分。
内置的函数len可以用于获取数组大小:
len(ar) = 3
数组是值类型
golang中的数组是值,而非C语言中的隐式指针。你可以获得数组的地址,并生成一个指向数组的指针(例如,将其高效地传递给函数):
func f(a [3]int) { fmt.Println(a) }
func fp(a *[3]int) { fmt.Println(a) }
func main() {
var ar [3] int
f(ar) // 传递一个ar的拷贝
fp(&ar) // 传递一个指向ar的指针
}
输出结果:
[0 0 0]
&[0 0 0]
数组字面值
所有的符合类型都有相同的值创建语法。以数组为例,其语法如下:
3个整数的数组:
[3]int{1, 2, 3}
10个整数的数组,前三个元素不是0:
[10]int{ 1, 2, 3}
不想数?使用…代表长度:
[...]int{1, 2, 3}
不想初始化所有值?使用key:value对:
[10]int{2:1, 3:1, 5:1, 7:1}
指向数组字面值的指针
你可以获取数组字面值的地址,这样可以得到一个指向新建数组实例的指针:
func fp(a *[3]int) { fmt.Println(a) }
func main() {
for i := 0; i < 3; i++ {
fp(&[3]int{i, i*i, i*i*i})
}
}
输出结果:
&[0 0 0]
&[1 1 1]
&[2 4 8]
2、切片(Slice)
切片
切片是对数组中某一段的引用。
切片比普通数组应用得更多也更广泛。
切片使用的代价很低。
一个切片类型很像一个没有大小的数组类型:
var a []int
内置的len(a)可以返回切片中元素的个数。
通过对数组或切片进行"切片",我们可以创建一个新切片:
a = ar[7:9]
a(上面例子中的a)的有效下标值是0和1;len(a) == 2。
切片速记
当对数组进行切片时,第一个下标值默认是0:
ar[:n]等价于a[0:n]。
第二个下标值默认为len(array/slice):
ar[n:]等价于ar[n:len(ar)]。
因此由数组创建切片时:
ar[:]等价于ar[0:len(ar)]。
切片引用数组
概念上:
type Slice struct {
base *elemType // 指向0th元素的指针
len int // 切片中元素的数量
cap int // 切片可以容纳元素的数量
}
数组:
ar: 7 1 5 4 3 8 7 2 11 5 3
切片:
a = ar[7:9] :base = &ar[7](指向ar中的2) len = 2 cap = 4
创建切片
切片字面值看起来像没有指定大小的数组字面值:
var slice = []int{1,2,3,4,5}
上面代码创建了一个长度为5的数组并创建一个切片用于引用这个数组。
我们可以使用内置的make函数分配一个切片(底层实际是个数组):
var s100 = make([]int, 100) // slice: 100 ints
为何用make而不是用new?因为我们需要创建切片,而不仅仅是为了分配内存。注意make([]int, 10)返回[]int,而new([]int)返回*[]int。
使用make创建切片、map以及channel。
切片容量
切片是对底层数组的一个引用。因此存在一些在数组里但却没在切片引用的范围内的元素。
内置的函数cap(capacity)用于报告切片可能增长到多长。
var ar = [10]int{0,1,2,3,4,5,6,7,8,9}
var a = ar[5:7] // 引用子数组{5,6}
len(a) = 2,cap(a) = 5,现在我们可以重新切片:
a = a[0:4] // 引用子数组 {5,6,7,8}
len(a)现在是4,而cap(a)依旧是5。
调整切片大小
切片可被当作可增长的数组用。使用make分配一个切片,并指定其长度和容量。当要增长时,我们可以做重新切片:
var sl = make([]int, 0, 100) // 长度 0, 容量 100
func appendToSlice(i int, sl []int) []int {
if len(sl) == cap(sl) { error(…) }
n := len(sl)
sl = sl[0:n+1] // 长度增加1
sl[n] = i
return sl
}
因此,sl的长度总是元素的个数,但其容量可根据需要增加。
这种手法代价很小,并且是Go语言中的惯用法。
切片使用的代价很小
你可以根据需要自由地分配和调整切片大小。它们的传递仅需要很小的代价;不必分配。
记住它们是引用,因此下层的存储可以被修改。
例如,I/O使用切片,而不是计数:
func Read(fd int, b []byte) int
var buffer [100]byte
for i := 0; i < 100; i++ {
// 每次向Buffer中填充一个字节
Read(fd, buffer[i:i+1]) // no allocation here
}
拆分一个Buffer:
header, data := buf[:n], buf[n:]
字符串也可以被切片,而且效率相似。
3、Maps
maps
Map是另外一种引用类型。它们是这样声明的:
var m map[string]float64
这里声明了一个map,索引key的类型为string,值类型为float64。这类似于C++中的类型*map
对于给定map m,len(m)返回key的数量。
map的创建
和创建一个切片一样,一个map变量是一个空引用;在可以使用它之前,应先要向里面放入一些内容。
三种方式:
1) 字面值:逗号分隔的key:value对列表
m = map[string]float64{"1":1, "pi":3.1415}
2) 创建
m = make(map[string]float64) // make not new
3) 赋值
var m1 map[string]float64
m1 = m // m1和m现在引用相同的map
map索引
(接下来的几个例子全都使用:
m = map[string]float64{"1":1, "pi":3.1415})
访问一个元素;如果该元素不存在,则得到对应map value类型的零值:
one := m["1"]
zero := m["not present"] // zero被置为0.0.
设置一个元素的值(两次设置将更新为最新值)
m["2"] = 2
m["2"] = 3 // 思维混乱
测试存在性
要测试一个map中是否存在某个key,我们可以使用一个多项赋值的"comma, om"形式:
m = map[string]float64{"1":1, "pi":3.1415}
var value float64
var present bool
value, present = m[x]
或者按惯例:
value, ok := m[x] // "comma ok" 形式
如果map中存在x这个key,布尔变量会被设置为true;value会被赋值为map中key对应的值。相反,布尔变量会被设置为false,value被设置为相应值类型的零值。
删除
使用多元赋值可以删除map中的一个值:
m = map[string]float64{"1":1.0, "pi":3.1415}
var keep bool
var value float64
var x string = f()
m[x] = v, keep
如果keep的值为true,则将v赋值到map中;如果keep为false,则删除map中的key x。因此删除一个key:
相关内容
- Go语言的代码组织结构详细介绍_Golang_
- Go语言基础知识总结(语法、变量、数值类型、表达式、控制结构等)_Golang_
- 创建第一个Go语言程序Hello,Go!_Golang_
- Go语言实现机器大小端判断代码分享_Golang_
- Fedora14 Linux系统安装Golang开发环境笔记_Golang_
- win7下配置GO语言环境 + eclipse配置GO开发_Golang_
- 在ubuntu下构建go语言开发环境的方法_Golang_
- Go语言开发环境搭建与初探(Windows平台下)_Golang_
- 我为什么喜欢Go语言(简洁的Go语言)_Golang_
- Go中map数据类型3点小知识_Golang_
