Go语言学习13-内建函数

内建函数

所谓内建函数,就是Go语言内部预约义的函数。调用它们的方式与调用普通函数并没有差别,而且在使用它们以前也不须要导入任何代码包。这里并不能把内建函数当作值来使用。由于它们并不像普通函数那样有隶属的Go语言数据类型。数组

1. close函数

内建函数 close 只接受通道类型的值(简称通道)做为参数。例如:数据结构

ch := make(chan int, 1)
close(ch)

调用这个 close 函数以后,会使做为参数的通道没法再接受任何元素值。若试图关闭一个仅能接受元素值的通道,则会形成一个编译错误。在通道被关闭以后,再向它发送元素值或者试图再次关闭它的时候,都会引起一个运行时恐慌。试图关闭一个为 nil 的通道值也会引起一个运行时恐慌。app

试图调用 close 函数关闭一个通道,并不会影响到在此调用以前已经发送的那些元素值,它们会被正常接收(若是存在接收操做的话)。可是,在此调用以后,全部的接收操做都会当即返回一个该通道的元素类型的零值。ide

2. len函数与cap函数

2.1 len函数的使用方法

参数类型 结果 备注
string string类型值的字节长度
[n]T或*[n]T 数组类型值长度,它等于n n表明了数组类型的长度,T表明了数组类型的元素类型
[]T 切片类型值的长度 T表明了切片类型的元素类型
map[K]T 字典类型值的长度,其中已包含的键的数量 K表明了字典类型的键类型,T表明了字典类型的元素类型
chan T 通道类型值当前包含的元素的数量 T表明了通道类型的元素类型

2.2 cap函数的使用方法

参数类型 结果 备注
[n]T或*[n]T 数组类型值长度,它等于n n表明了数组类型的长度,T表明了数组类型的元素类型
[]T 切片类型值的容量 T表明了切片类型的元素类型
chan T 通道类型值的容量 T表明了通道类型的元素类型

对于一个切片类型值来讲,它的长度和容量的关系:函数

0 <= len(s) <= cap(s)性能

一个切片值的容量就是它拥有的那个底层数组的长度。这个底层数组的长度一定不会小于该切片值的长度。学习

值为 nil切片类型值字典类型通道类型值 的长度都是 0 。值为 nil切片类型值通道类型值 的容量也都是 0.net

若是 s 是一个 string 类型的常量,那么表达式 len(s)cap(s) 也都等同于常量。len(s) 所表明的值在编译期间就会被计算出来。若是 s 是一个表达式,且其类型是数组类型或指向数组类型的指针类型,那么只要该表达式中不包含通道接收操做和函数调用操做,它就不会被求值。由于 s 的类型中已经包含了它的长度信息。在对表达式 len(s)cap(s) 进行求值的时候并不须要求得 s 的结果值而只须要从 s 的类型中取得其长度便可。在这种状况下,这两个表达式也会等同于常量。指针

3. new函数和make函数

这两个函数是专门用于数据初始化。这里的数据初始化是指对某个数据类型的值或变量的初始化。在Go语言中,几乎全部的数据类型的值均可以使用字面量来进行表示和初始化。在大多数状况下,使用字面量就能够知足初始化值或变量的要求。code

3.1 new

内建函数 new 用于为值分配内存。它并不会去初始化分配到的内存,而只会清零它。例如:

new(T)

如上调用该表达式求值时,所作的是为 T 类型的新值分配并清零一块内存空间,而后将这块内存空间的地址做为结果返回。而这个结果就是指向这个新的 T 类型值的指针值。它的类型为 *Tnew* 函数返回的 T 类型值老是指向一个 T** 类型的零值。例如:

new(string) // 求值结果指向的是一个string类型的零值""
new([3]int) // 求值结果指向的是一个[3]int类型的零值[3]int{0,0,0}

以标准库代码包 bytes 中的结构体类型 Buffer 为例, bytes.Buffer 是一个尺寸可变的字节缓冲区。它的零值就是一个当即可用的空缓冲区。例如:

// 求值结果就是一个指向一个空缓冲区的指针值,能够当即在这个缓冲区上进行读写操做
new(bytes.Buffer)

标准库代码包 sync 中的结构体类型 Mutex 也是一个能够 new 后即用的数据类型。它的零值就是一个处于未锁定状态的互斥量。

3.2 make

内建函数 make 只能被用于建立切片函数、字典类型和通道类型的值,并返回一个已被初始化的(即非零值的)的对应类型的值。以上3个复合类型的特殊结构都是引用类型,在它们的每个值的内部都会保持着一个对某个底层数据结构值的引用。若是不对它们的值进行初始化,那么其中的这种引用关系是不会创建起来的,同时相关的内部值也会不正确。所以在建立这3个引用类型的值的时候,必须将内存空间分配和数据初始化这两个步骤绑定在一块儿。

内建函数 make 除了会接受一个表示目标类型的类型字面量以外,还会接受一个或两个额外的参数。

对于切片类型来讲,能够把新值的长度和容量也传递给 make 函数,例如:

make([]int, 10, 100)

如上建立了一个新的 [ ]int 类型的值,这个值的长度为 10,容量为 100。若是省略最后一个参数,即不指定新值的容量。这样的话,该值的容量会与其长度一致。例如:

s := make{[]int, 10}

变量 s 的类型是 [ ]int 的,而长度和容量都是 10

在使用 make 函数初始化一个切片值的过程当中,该值会引用一个长度与其容量相同且元素类型与其元素类型一致的数组值。这个数组值就是该切片值的底层数组。该数组值中每一个元素都是当前元素类型的零值。可是,切片值只会展示出数量与其长度相同的元素。所以 make([ ]int, 10, 100) 所建立并初始化的值就是 [ ]int{0,0,0,0,0,0,0,0}

在使用 make 函数建立字典类型的值的时候,也能够指定其底层数据结果的长度。可是,该字典值只会展现出咱们明确“放入”的键值对。例如:

make(map[string]int, 100)

它所建立和初始化的值会使 map[string]int{}。虽然能够忽略那个用于表示底层数据结构长度的参数,可是这边仍是建议:应该在性能敏感的应用场景下,根据这个字典值可能包含的键值对的数量以及“放入”它们的时间,仔细地设置该长度参数。

对于通道类型的值的数据初始化,这里可使用 make 函数建立一个通道类型的值:

make(chan int, 10)

其中的第一个参数表示的是通道的类型,而第二个参数则表示该通道的长度。与字典类型相同,第二个参数也能够被忽略掉。对于忽略它的含义,在以后的博文中详细讲解通道类型的时候你们能够了解。

内建函数 make 只能被应用在引用类型的值的建立上。而且,它的结果是第一个参数所表明的类型的值,而不是指向这个值的指针值。若是想要获取该指针值的话,只须要以下:

m := make(map[string]int , 100)
mp := &m

对于数据初始化须要考虑的一些规则:

  1. 字面量能够被用于初始化几乎全部的Go语言数据类型的值,除了接口类型和通道类型。接口类型没有值,而通道类型的值只能使用 make 函数来建立。若是须要指向值的指针值,能够在表示该值的字面量之上进行取址操做。

  2. 内建函数 new 主要用于建立值类型的值。调用 new 函数的额表达式的结果值将会是指向被建立值的指针值,而且被建立值会是其所属数据类型的零值。所以,new 函数不适合被用来建立引用类型的值。其直接的缘由是引用类型的值的零值都是 nil,是不可用的。

  3. 内建函数 make 仅被用于某些引用类型(切片类型、字典类型和通道类型)的指的建立。它在建立值以后还会对其进行必要的初始化。与 new 函数不一样,调用 make 函数的表达式的结果值将会是被建立的值自己,而不是指向它的指针值。

4. append函数和copy函数

append 函数和 copy 函数都被用于辅助在切片类型值之上的操做,这部份内容参考 Go语言学习5-切片类型

5. delete函数

内建函数 delete 专用于删除一个字典类型值中的某个键值对。它接受两个参数,第一个参数是做为目标的字典类型值,而第二个参数则是可以表明要删除的那个键值对的键。例如:

delete(m, k)

这里有两点须要注意:

  • 第二个参数 km 的键的类型之间必须知足赋值规则。
  • m 的值是 nil 或者 k 所表明的键值对并不存在于 m 中的时候,delete(m, k) 不会作任何操做。在没有可删除的目标的时候,删除操做将被忽略。这种删除失败不会被反馈。

6. complex 函数、real 函数和 imag 函数

这3个内建函数都是专用于操做复数类型值的。

complex 函数被用于根据浮点数类型的实部和虚部来构造复数类型。例如:

var cplx128 complex128 = complex(2, -2)

内建函数 realimag 则分别被用于从一个复数类型值中抽取浮点数类型的实部部分和浮点数类型的虚部部分。例如:

var im64 = imag(cplx128)
var r64 = real(cplx128)

对于 complex 函数来讲,两个参数的类型必须是同一种浮点数类型,而且其结果类型与参数类型对应。在Go语言中,对于复数有一个恒等式:

z == complex(real(z), imag(z)) // z是一个复数类型的变量

注意: 若是 complex 函数的两个参数都没有显示的类型,那么该函数的结果的类型将会是 complex128 类型的。若是 complex 函数的参数都是常量,那么它的结果值也必是常量。

7. panic函数和recover函数

内建函数 panic 函数和 recover 函数分别被用于报告和处理运行时恐慌。

函数 panic 只接受一个参数。这个参数能够是任意类型的值。按照惯例,panic 函数的实际参数的类型经常是接口类型 error 的某个实现类型。panic 函数的参数都应该足以表示恐慌发生时的异常状况。

函数 recover 不接受任何参数,可是返回一个 interface{} 类型的结果值。interface{} 就是空接口。全部的数据类型都是它的实现类型。所以,recover 函数的结果值多是任何类型的。这是与 panic 函数的那个惟一参数相对应的,它们都是 interface{} 类型的。若是运行时恐慌的报告是经过调用 panic 函数来进行的话,那么以后调用 recover 函数所得的结果值就应该是先前 panic 函数在被调用时接受的那个参数值。recover 函数的结果值也有可能 nil 。若是是 nil,属于如下的状况:

  • 传递给panic函数的参数值就是nil。
  • 运行时恐慌根本就没有发生。狭义的讲,panic函数没有被调用。
  • 函数recover并无在defer语句中被调用。

在任何状况下任何位置上调用 recover 函数都不会产生任何反作用。若是不用它来处理运行时恐慌,那么对它的调用也就没有任何意义了。panic 函数和 recover 函数之间确定是存在着某种联系,在后面的博文中将对异常报告和处理的更多细节进行讲解。

8. print函数和println函数

函数 print 的做用是依次(即从左到右)打印出传递给它的参数值,每一个参数值对应的打印内容都由它们的具体实现决定。而函数 println 函数则会在 print 函数打印的内容的基础上再在每一个参数之间加入空格,并在最后加入换行符。例如:

print("A", 12.4, 'R', "C")
println("A", 12.4, 'R', "C")

调用表达式被求值以后,出现内容:

A+1.240000e+00182CA +1.240000e+001 82 C

对于上面的这两个函数,有如下须要注意:

  • 它们接受的参数只能是有限的数据类型的值。而且,在这些受支持的数据类型当中。大部分都是Go语言的基础数据类型。

  • 这两个函数针对于每种受支持的数据类型的打印格式都是固定的,没法自定义。

Go语言并不保证会在之后的版本中一直保留这两个函数。所以,尽可能不要在程序中使用这两个函数,尤为是用于生产环境的程序。应该使用标准库代码包 fmt 中的函数 PrintPrintln 来替代它们。

结语

至此,Go语言数据的使用 就讲完了,下篇博文将要介绍 Go语言流程控制方法,敬请期待!!!

相关文章
相关标签/搜索