这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天
希望这个文章可以帮助新接触go语言的同学们少踩一些坑,正题开始
go语言语法简单,开发效率高,规范性好,并且拥有垃圾自动回收机制
常量 :
在go语言中,使用const关键字来声明常量,不能对常量进行寻址操作,不然会报错 cannot take the a of b, 在声明的时候可以省略类型也可以指定类型,如下列代码所示
const a = 123456
const b = 1.2345
const c int = 123
const d float64 = 1.2345
字符串
- 在程序开发的过程中,很多操作都离不开字符串,下面是定义字符串的方法
var s = "golang"
var s = `golang`
var ss string = "golang"
var ss string = `golang`
- go语言中采用utf-8的编码方式,上例的每个字母都只占用一个字节,而汉字会占据三个字节,与c++不同的是,go里面的字符串不能直接进行修改,要先将其转换成字节数组进行修改,如下列代码所示
s := "hello world"
a := []byte(s)
a[1]='a'
s := string(s) //s="hallo world"
- 下面介绍几个常用的字符串拼接方法
使用 "+" 进行拼接 :
s := "aaa"
d := "bbb"
c := a + b //c = "aaabbb"
使用fmt.Sprintf进行拼接 :
s := "go"
d := "lang"
s = fmt.Sprintf("%s%s",s,d) //s="golang"
使用strings.Builder :
这么写的好处因为省去了 []byte 和 string 之间的转换,内存分配次数还减少了 1 次,内存消耗减半,性能比前两个大大提高,如果有很多需要待拼接的字符串,尽量使用该方法进行拼接
a := "aaa"
b := "bbb"
var builder strings.Builder
builder.WriteString(b)
builder.WriteString(a)
s := builder.String() //s="bbbaaa"
数组
go语言的数组不能进行扩容,在复制和传递过程中均为值复制,所以尽量不要进行大数组的复制,下面是声明数组的三种方式
var arr [5]int
var arr2 = [3]int{0,1,2}
arr3 := [...]int{0,1,2,3} //...是golang中的语法糖,自动推算数组大小
切片
切片是go语言中一个非常重要的数据结构,在这里值得一提的是,slice虽然为引用类型(包括后续的map , channel),但本质上依旧是值复制,下面来看一看runtime包中的切片底层代码
type slice struct{
array unsafe.Pointer
len int
cap int
}
在slice结构体中总共有三个字段,分别是指向底层数组的指针array,切片长度len和容量cap,引用类型默认全是浅拷贝,即复制指向对象的指针,使用len(slice)和cap(slice)方法获取切片的长度和容量时,时间复杂度为O(1)
下面是定义切片和添加数据的几种方法
//定义方法
var s1 []int
s2 := make([]int,3)
s3 := make([]int,3,3)
s4 := []int{1,3,4,5)
//添加数据方法
s5 := make([]int,2)
s5[0] = 1
s5[1] = 3 //s5 = {1,3}
s5 = append(s5,5,4) //s5 = {1,3,5,4}
s5 = append(s5,s4...) //s5 = {1,3,5,4,1,3,4,5}
如果定义了一个切片a和切片b ,然后a = b , 那么两个切片指向的底层数组是同一个,那么如果我们只是想单纯将切片a的值复制到另一个切片b上该怎么做的,那么引出了 copy函数
s := []int{1,3,4}
a := make([]int,3)
copy(a,s) //a为复制的目标,s为数据来源 a = {1,3,4}
下面介绍一下切片的截取
num := []int{1,2,3,4,5,6,7}
num1 := num[3:5] //左闭右开 num1 = {4,5}
num2 := num[ :2] //num2 = {1,2}
num3 := num[4: ] //num3 = {5,6,7}
那么,如果我们想删除切片的其中一个值呢,go语言是不支持删除切片元素的语法的,那么我们可以使用切片的截取方法来删除
//比如我们要删除num切片中的'3'
num = append(num[:2],num[3:]...)
//删除第一个元素
num = num[1:]
//删除最后一个元素
num = num[0:len(num)-1]
切片使用make初始化时,如果大于64kb,那么将逃逸到堆区,小于64kb的切片直接在栈中初始化,当添加元素时容量超过了现有容量,如果切片旧容量小于1024,那新申请的容量为之前的二倍,大于1024将会增加原来的四分之一,扩容时,将会重新分配一个更大的内存,将原切片数据拷贝过来。