Go 语法入门 | 青训营

51 阅读4分钟

指针

与C相同,Go语言让程序员决定何时使用指针。变量其实是一种使用方便的占位符,用于引用计算机内存地址。Go 语言中的的取地址符是&,放到一个变量前使用就会返回相应变量的内存地址。

指针声明和初始化

和基础类型数据相同,在使用指针变量之前我们首先需要申明指针,声明格式如下:var var_name *var-type,其中的var-type 为指针类型,var_name 为指针变量名,* 号用于指定变量是作为一个指针。

指针的初始化就是取出相对应的变量地址对指针进行赋值,具体如下

var a int= 20 /* 声明实际变量 */ var ip int / 声明指针变量 / ip = &a / 指针变量的存储地址 */

数组

以上就可以定一个一维数组,我们举例代码如下 var balance [10] float32 在go语言中,数组名仅仅表示整个数组,是一个完整的值,一个数组变量即是表示整个数组。 所以在go中一个数组变量被赋值或者被传递的时候实际上就会复制整个数组。如果数组比较大的话,这种复制往往会占有很大的开销。所以为了避免这种开销,往往需要传递一个指向数组的指针,这个数组指针并不是数组。关于数组指针具体在指针的部分深入的了解。 通过数组和指针的知识我们就可以定义一个数组指针,代码如下: var a = [...]int{1, 2, 3} // a 是一个数组 var b = &a // b 是指向数组的指针 数组指针除了可以防止数组作为参数传递的时候浪费空间,还可以利用其和for range来遍历数组,具体代码如下` for i, v := range b { // 通过数组指针迭代数组的元素 fmt.Println(i, v) }

字符串

字符串定义和初始化

Go语言字符串的底层结构在reflect.StringHeader中定义,具体如下: type StringHeader struct { Data uintptr Len int } 也就是说字符串结构由两个信息组成:第一个是字符串指向的底层字节数组,第二个是字符串的字节的长度。

字符串其实是一个结构体,因此字符串的赋值操作也就是reflect.StringHeader结构体的复制过程,并不会涉及底层字节数组的复制,所以我们也可以将字符串数组看作一个结构体数组。

字符串和数组类似,内置的len函数返回字符串的长度。

字符串UTF8编码

根据Go语言规范,Go语言的源文件都是采用UTF8编码。因此,Go源文件中出现的字符串面值常量一般也是UTF8编码的(对于转义字符,则没有这个限制)。 Go语言的字符串中可以存放任意的二进制字节序列,而且即使是UTF8字符序列也可能会遇到坏的编码。如果遇到一个错误的UTF8编码输入,将生成一个特别的Unicode字符‘\uFFFD’,这个字符在不同的软件中的显示效果可能不太一样,在印刷中这个符号通常是一个黑色六角形或钻石形状,里面包含一个白色的问号‘�’。

slice

切片就是一种简化版的动态数组。因为动态数组的长度不固定,切片的长度自然也就不能是类型的组成部分了。数组虽然有适用它们的地方,但是数组的类型和操作都不够灵活,而切片则使用得相当广泛。 切片高效操作的要点是要降低内存分配的次数,尽量保证append操作(在后续的插入和删除操作中都涉及到这个函数)不会超出cap的容量,降低触发内存分配的次数和每次分配内存大小。

slice定义

我们先看看切片的结构定义 type SliceHeader struct { Data uintptr // 指向底层的的数组指针 Len int // 切片长度 Cap int // 切片最大长度 }内置的len函数返回切片中有效元素的长度,内置的cap函数返回切片容量大小,容量必须大于或等于切片的长度。 切片可以和nil进行比较,只有当切片底层数据指针为空时切片本身为nil,这时候切片的长度和容量信息将是无效的。如果有切片的底层数据指针为空,但是长度和容量不为0的情况,那么说明切片本身已经被损坏了

个人思考

go语言的指针 数组 字符串以及slice都在c语言基础上进行了取其精华去其糟粕的优化。这次对go语言语法的学习让我感受到了go语言的魅力。