在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
一.值,指针和引用类型 与C和C++不同 Go语言中的数组是按值传递的,所以传递一个大数组的代价特别大,幸运的是,在Go语言中不常用数组,因为我们可以用切片代替(所以切片和数组到底有什么区别?) 当一个变量传入函数时,会复制该变量的值到该函数作用域,所以本地变量在不使用时会自动被垃圾回收,很多情况下我们希望自己来管理变量的生命周期而非由它的作用域决定。所以通过使用指针,我们可以让参数的传递成本最低,且内容可修改,且变量的生命周期独立于作用域。 指针的操作与C类似,&用作取址操作,*用于取值操作指针在这里的操作以及与++,--的优先级同C中的指针部分相似,所以这里我就不细讲了。 Go语言的自动内存管理机制使得使用取址操作符&来取得函数参数或本地变量的地址非常安全,因为Go语言中只要一个指针引用一个变量那个变量就会在内存中保留。若在C及C++中这么操作非静态变量将会非常麻烦!(费解?有待考虑) 在一些场景,我们需要传递非引用类型的可修改值,或需要高效的传入大类型的值,这时候需要使用到指针,Go语言提供了两种,创建变量的语法,同时获得指向它们的指针: 1.使用内置的new()函数。 2.使用地址操作符。 如: type composer struct{ name string birthYear int } 一些初始化方法 1. antony := composer{“antony davis”,1994} 2. antopoint := new (compser) antopoint.name,antopoint. birthYear = “antony”,1994 3. antopoint :=&composer{} antopoint.name,antopoint. birthYear = “antony”,1994 4. antopoint :=&composer{“antony”,1994}
fmt.Println(antony)-> {“antony davis”,1994}输出结构体值 fmt.Println(antopoint)-> &{“antony”,1994}输出结构体值前面加一个&表示该变量是指针类型 new(Type) = &Type{}均分配了Type类型的空值同时返回指向该值的指针,并且该值的生命周期会被Go语言的内存管理系统打理(感觉Go的内存管理系统真是牛逼,什么都做!) 切片和映射都是引用类型(之后解释,还包括通道,函数,方法),保存引用类型的变量非常廉价(64位机器上,一个切片占16字节,一个映射占8字节)。其使用语法与变量值一样。所以当我们需要传递大量值的情况下,使用切片来传递,若这些值各异,使用一个指向结构体的指针。 fun inflate(numbers []int,factor int){//s使用切片作为参数,可以直接对该切片指向的值进行修改。 for i:=range numbers{//没有使用for i,number := range numbers然后对number进行操作,因为这样得到的number是复制的值,不能直接作用于numbers,使得修改无效。 numbers[i] *=factor } } 二 数组和切片的区别: 数组是一个定长的序列,数组在初始化的过程中对长度就已经设定,数组的长度都是固定的并且不可修改的,所以数组的容量cap()和长度len()相等如: [length]Type [N] Type{value1,value2,value3…,valueN} […] Type{value1,value2,value3…,valueN}//[]内使用...操作符表示自动计算数组的长度。 而切片是一个容量固定,长度可变的相同类型元素的序列,容量就是指最多能装下数据的个数,长度则是实际装下数据的个数。但是切片的容量还可以通过append()函数来增长,切片的初始化如下: make([]Type,length,capacity)//马克用于创建切片,映射和通道 make([]Type,length) []Type{} []Type{value1,value2,value3…,valueN}//[]内为空即是切片 一些常用的切片操作(数组和切片均可以采用这些操作来进行切片):s[n],s[n:m],s[n:],s[:m],s[:](从切片索引0到len(s)-1所获得得切片),s[:cap(s)](增加切片的长度到切片的容量) 三 索引与分割切片 一个切片是一个隐藏数组的引用(这里对引用的概念还是很模糊),对于该切片的切片也是引用于同一数组,所以只要对该数组的切片进行修改,该数组就会被修改且直接影响其它切片。 结构体指针切片的使用: type Product struct{ name string price float64 } products:=[]*Product{{“Dennis”,49},{“Box”,90}}//product为结构体指针切片 for _,product :=range products{ product.price+=0.50//这里的修改直接作用于原结构体数据,因为该for range复制的product是一个指向结构体的指针,直接作用于该结构体 } 四 切片的修改 1.如果我们需要往切片末尾中追加元素,可以使用内置的append()函数。如果我们向向该切片中追加另一个切片,我们必须使用...操作符来告诉Go语言把被添加进来的切片当成多个元素 s = append(s,”h”,”i”,”j”)//添加多个单一的值 s = append(s,t…)//添加切片t中的所有值 s = append(s,u[2:5]…)//添加一个子切片中的所有元素 b = append(b,letters…)//b为一个字节切片,letters为字符串,将一个字符串字节添加进一个字节切片中去。 2.如果我们想要在切片的指定位置插入元素,可使用InsertStringSliceCopy()函数 s:=[]string{“M”,”N”,”S”,”T”} x:=InsertStringSliceCopy(s,[]string{“a”,”b”,”c”},0)在开头插入切片,0为插入位置,当0改为len(s)则是在末尾插入切片。 3.如果我们想要复制切片中的内容,可以使用copy()函数 copy(slicetarget,slicesource)将源切片中的内容复制到目标切片中去,返回所复制元素的个数,如果目标切片的长度不够来容纳源切片中的项,则无法容纳的部分将会被忽略 4.相对于InsertStringSliceCopy还有一个切片插入函数InserStringSlice()使用方法与InsertStringSliceCopy一样,但是InserStringSlice会修改原始切片,并不是得到一个插入后的全新切片,而是直接在原切片上修改。 5.切片的删除操作非常简单,使用相应的切片操作即可如:s = s[2:]//删除0~1头部元素,s = s[:5]//删除索引为5以后的尾部元素 ,s=append(s[:1],s[5:])//从中间删除s[1:5],若想要不改变原始切片可以使用RemoveStringSliceCopy(s,start,end),s为切片,start为起始索引,end为结束索引,同理对应的直接修改切片的函数为RemoveStringSlice(s,start,end) 6.对切片的搜索排序 |
请发表评论