Go 语言 15 个内置函数详解

简介: Go 语言 15 个内置函数详解

介绍

Go 语言为了方便我们开发,提供了 15 个内置函数,比如 lencapmakenew 等。

本文我们结合 Go 内置函数官方文档[1],介绍一下 Go 语言中的内置函数。

内置函数

内置函数 append 可以将元素追加到切片的末尾。

func append(slice []Type, elems ...Type) []Type

当我们使用 append 向切片中追加元素时,切片的底层数组必须具有足够的容量,否则,将会分配一个新的底层数组。

func main() {
 s := []int{1, 2, 3}
 fmt.Printf("%p %d\n", s, s)
 s = append(s, 4)
 fmt.Printf("%p %d\n", s, s)
}

输出结果:

0xc0000b2018 [1 2 3]
0xc0000ae030 [1 2 3 4]

所以,我们需要注意的是,append 之后的切片赋值给同一个变量

除了使用 append 向切片中追加元素之外,我们还可以向切片中追加另一个切片,例如:

s1 := []int{5, 6, 7}
s = append(s, s1...)

此外,还可以使用 append 将字符串追加到字节切片中,例如:

str := "hello "
bs := append([]byte(str), "world"...)

内置函数 copy 可以将源切片中的元素拷贝到目标切片。

func main() {
 src := []string{"go", "vue"}
 dst := make([]string, 2)
 n := copy(dst, src)
 fmt.Printf("%s %d\n", dst, n)
}

输出结果:

[go vue] 2

copy 的返回值是拷贝元素的个数,返回值是 len(src)len(dst) 的最小值。

需要注意的是,源切片和目标切片中的元素可能会重叠。

此外,还可以使用 copy 将一个字符串中的字节拷贝到一个字节切片中,例如:

func main() {
 str := "hello"
 bs := make([]byte, 5)
 n := copy(bs, str)
 fmt.Printf("%s %d\n", bs, n)
}

内置函数 delete 通过指定键 m[key] 删除 map 中的元素。

如果 mapnil 或没有元素,delete 不做任何操作。

func main() {
 var m map[int]string
 fmt.Println(m)
 delete(m, 0)
 fmt.Println(m)
 m1 := make(map[int]string)
 fmt.Println(m1)
 delete(m1, 0)
 fmt.Println(m1)
 m2 := make(map[int]string, 2)
 m2[0] = "hello"
 m2[1] = "world"
 fmt.Println(m2)
 delete(m2, 0)
 fmt.Println(m2)
}

输出结果:

map[]
map[]
map[]
map[]
map[0:hello 1:world]
map[1:world]

内置函数 len 返回值的长度,值的类型不同,值的长度含义也不同。

  • array 数组中元素的个数。
  • *array 数组指针中元素的个数,即使数组指针的值是 nil
  • slicemap 切片或映射中元素的个数,如果切片或映射的值是 nillen(v) 值的长度是 0。
  • string 字符串中字节的个数。
  • channel 通道缓冲区中未读元素的个数,如果缓冲通道的值是 nillen(v) 值的长度是 0。
func main() {
 arr := [3]int{1, 2, 3}
 fmt.Println(arr)
 fmt.Println(len(arr))
 var arr1 *[3]int
 fmt.Println(arr1)
 fmt.Println(len(arr1))
 var s []int
 fmt.Println(len(s))
 s = []int{1, 2, 3}
 fmt.Println(len(s))
 var m map[int]string
 fmt.Println(len(m))
 m = make(map[int]string)
 m[0] = "hello"
 fmt.Println(len(m))
 str := "frank"
 fmt.Println(len(str))
 var c chan int
 fmt.Println(c)
 fmt.Println(len(c))
 c = make(chan int)
 fmt.Println(len(c))
}

输出结果:

[1 2 3]
3
<nil>
3
0
3
0
1
5
<nil>
0
0

需要注意的是,slicemapchannel 必须先使用内置函数 make 初始化后,该类型的值才可以使用。

内置函数 cap 返回值的容量,值的类型不同,值的容量含义也不同。

  • array 数组中元素的个数,数组的 cap(v)len(v) 相等。
  • *array 数组指针中元素的个数,数组指针的 cap(v)len(v) 相等。
  • slice 切片可以容纳元素的最大长度,如果切片的值是 nil,该切片 cap(v) 值的容量是 0。
  • channel 通道缓冲区的容量,如果通道的值是 nil,该通道 cap(v) 值的容量是 0。
func main() {
 var arr [3]int
 fmt.Println(arr)
 fmt.Println(cap(arr))
 var arr1 *[3]int
 fmt.Println(arr1)
 fmt.Println(cap(arr1))
 var s []string
 fmt.Println(s)
 fmt.Println(cap(s))
 s = make([]string, 1)
 s[0] = "go"
 fmt.Println(s)
 fmt.Println(cap(s))
 var c chan int
 fmt.Println(c)
 fmt.Println(cap(c))
}

输出结果:

[0 0 0]
3
<nil>
3
[]
0
[go]
1
<nil>
0

内置函数 make 仅限为 slicemapchannel 分配内存并初始化。

func make(t Type, size ...IntegerType) Type

make 第一个参数是类型,而不是值;第二个参数是可选(变长)参数,整型类型的值,返回值是该类型的值本身。

需要注意的是,第一个参数不同(不同类型),第二个参数的含义不同。

  • slice 第一个参数是切片类型,第二个参数的含义是指定切片的长度。如果没有传递第三个参数(整型类型的值),切片的容量等同于切片的长度,否则,切片的容量等同于第三个参数的值,需要注意的是,切片的容量必须不小于切片的长度。
  • map 分配一个有足够空间可以容纳指定数量元素的空映射,第二个参数可以省略,如果省略第二个参数,将分配一个起始值 0。
  • channel 指定缓冲区大小,初始化通道,如果第二个参数省略,或指定值为 0,该通道将被初始化为一个无缓冲通道。

内置函数 new 也可以分配内存,与 make 的区别是,它仅分配内存,而未初始化。

make 相同,第一个参数是类型,而不是值;

make 不同,返回值是新分配的类型零值的指针。

内置函数 complex 将两个浮点型的值构造为一个复合类型的值,需要注意的是,实部和虚部必须是相同类型,即都是 float32float64

返回值是对应的复合类型,即 complex64 对应 float32complex128 对应 float64

内置函数 real 用于返回复合类型的值的实部,返回值是对应的浮点数类型。

内置函数 imag 用于返回复合类型的值的虚部,返回值是对应的浮点数类型。

注意:complexrealimag 三个内置函数,一般不常用,读者朋友们只需简单了解即可。

内置函数 close 关闭通道,被关闭的通道必须是一个双向通道或仅支持发送的单向通道。

并且 close 应该由发送者执行,结果是在最后一个发送的值被接收后,关闭该通道。

通道被关闭后,任何该通道的接收者将返回成功而不会阻塞,接收者得到的返回值是该通道的类型零值和一个布尔类型的零值 false

需要注意的是,不仅是关闭通道会返回 false,空通道也会返回 false

内置函数 panic 停止当前 goroutine 正常执行,当一个函数 F 调用 panic 时,该函数 F 立即停止正常执行。

该函数 F 通过 defer 延迟调用的任意函数,仍然会执行,并将执行结果返回给 F 调用者。

对于 F 的调用者 F2,调用 F 也会像调用 panic,停止 F2 的执行,并运行 F2 通过 defer 延迟调用的任意函数。以此类推,一直持续到当前 goroutine 中的所有函数都以相反的顺序停止运行。

此时,程序以非 0 退出代码终止运行。

以上终止程序运行的序列称为“恐慌”,可以通过接下来我们要介绍的内置函数 recover 进行控制。

内置函数 recover 允许程序管理“恐慌”的 goroutine 的行为。

可以在 defer 中调用 recover 恢复正常执行来停止“恐慌”,并且检索导致“恐慌”的错误。

但是,如果在 defer 之外调用 recover,它不会恢复正常执行来停止“恐慌”。此种情况,recover 的返回值是 nil。此外,当前执行 recovergoroutine 未“恐慌”,或调用 panic(nil) 时,recover 的返回值也是 nil

因此,我们可以通过 recover 的返回值,判断当前 goroutine 是否“恐慌”。

注意:此处讲的在 defer 中调用 recover,是指在 defer 本身中,而不是任何被 defer 调用的函数中。

内置函数 print 可以通过指定格式来格式化其参数,并将结果输出。

内置函数 println 可以通过指定格式来格式化其参数,并将结果输出。与 print 的区别是,参数之间会添加空格,末尾会添加换行符。

注意:printprintln 与标准库 fmt 中的 fmt.Print()fmt.Println() 的区别是,前者是标准错误输出,后者是标准输出。在 Go 语言开发中,官方推荐使用标准库 fmt 包,感兴趣的读者朋友们可以查阅相关资料进一步了解。

03

总结

本文我们介绍 Go 语言的内置函数,读者朋友们需要重点掌握的内置函数是 lencapmakenewappendcopydeleteclosepanicrecover

Go 语言作为静态编程语言,分为编译期和运行时,Go 语言的内置函数的底层原理,感兴趣的读者朋友们可以阅读 Go 语言内置函数的源码[2]

推荐阅读:

参考资料

[1]

Go 内置函数官方文档: https://pkg.go.dev/builtin@go1.20.3

[2]

Go 语言内置函数的源码: https://cs.opensource.google/go/go/+/refs/tags/go1.20.3:src/cmd/compile/internal/typecheck/universe.go

目录
相关文章
|
8天前
|
监控 算法 Go
Golang深入浅出之-Go语言中的服务熔断、降级与限流策略
【5月更文挑战第4天】本文探讨了分布式系统中保障稳定性的重要策略:服务熔断、降级和限流。服务熔断通过快速失败和暂停故障服务调用来保护系统;服务降级在压力大时提供有限功能以保持整体可用性;限流控制访问频率,防止过载。文中列举了常见问题、解决方案,并提供了Go语言实现示例。合理应用这些策略能增强系统韧性和可用性。
37 0
|
1天前
|
存储 编译器 Go
Go语言学习12-数据的使用
【5月更文挑战第5天】本篇 Huazie 向大家介绍 Go 语言数据的使用,包含赋值语句、常量与变量、可比性与有序性
28 6
Go语言学习12-数据的使用
|
2天前
|
Java Go
一文带你速通go语言指针
Go语言指针入门指南:简述指针用于提升效率,通过地址操作变量。文章作者sharkChili是Java/CSDN专家,维护Java Guide项目。文中介绍指针声明、取值,展示如何通过指针修改变量值及在函数中的应用。通过实例解析如何使用指针优化函数,以实现对原变量的直接修改。作者还邀请读者加入交流群深入探讨,并鼓励关注其公众号“写代码的SharkChili”。
9 0
|
2天前
|
存储 缓存 Java
来聊聊go语言的hashMap
本文介绍了Go语言中的`map`与Java的不同设计思想。作者`sharkChili`是一名Java和Go开发者,同时也是CSDN博客专家及JavaGuide项目的维护者。文章探讨了Go语言`map`的数据结构,包括`count`、`buckets指针`和`bmap`,解释了键值对的存储方式,如何利用内存对齐优化空间使用,并展示了`map`的初始化、插入键值对以及查找数据的源码过程。此外,作者还分享了如何通过汇编查看`map`操作,并鼓励读者深入研究Go的哈希冲突解决和源码。最后,作者提供了一个交流群,供读者讨论相关话题。
12 0
|
3天前
|
Java Go
Go语言学习11-数据初始化
【5月更文挑战第3天】本篇带大家通过内建函数 new 和 make 了解Go语言的数据初始化过程
17 1
Go语言学习11-数据初始化
|
4天前
|
自然语言处理 安全 Java
速通Go语言编译过程
Go语言编译过程详解:从词法分析(生成token)到句法分析(构建语法树),再到语义分析(类型检查、推断、匹配及函数内联)、生成中间码(SSA)和汇编码。最后,通过链接生成可执行文件。作者sharkchili,CSDN Java博客专家,分享技术细节,邀请读者加入交流群。
22 2
|
4天前
|
Java Linux Go
一文带你速通Go语言基础语法
本文是关于Go语言的入门介绍,作者因其简洁高效的特性对Go语言情有独钟。文章首先概述了Go语言的优势,包括快速上手、并发编程简单、设计简洁且功能强大,以及丰富的标准库。接着,文章通过示例展示了如何编写和运行Go代码,包括声明包、导入包和输出语句。此外,还介绍了Go的语法基础,如变量类型(数字、字符串、布尔和复数)、变量赋值、类型转换和默认值。文章还涉及条件分支(if和switch)和循环结构(for)。最后,简要提到了Go函数的定义和多返回值特性,以及一些常见的Go命令。作者计划在后续文章中进一步探讨Go语言的其他方面。
10 0
|
5天前
|
JavaScript 前端开发 Go
Go语言的入门学习
【4月更文挑战第7天】Go语言,通常称为Golang,是由Google设计并开发的一种编程语言,它于2009年公开发布。Go的设计团队主要包括Robert Griesemer、Rob Pike和Ken Thompson,这三位都是计算机科学和软件工程领域的杰出人物。
13 1
|
5天前
|
Go
|
6天前
|
分布式计算 Java Go
Golang深入浅出之-Go语言中的分布式计算框架Apache Beam
【5月更文挑战第6天】Apache Beam是一个统一的编程模型,适用于批处理和流处理,主要支持Java和Python,但也提供实验性的Go SDK。Go SDK的基本概念包括`PTransform`、`PCollection`和`Pipeline`。在使用中,需注意类型转换、窗口和触发器配置、资源管理和错误处理。尽管Go SDK文档有限,生态系统尚不成熟,且性能可能不高,但它仍为分布式计算提供了可移植的解决方案。通过理解和掌握Beam模型,开发者能编写高效的数据处理程序。
134 1