Golang02-指针、数组、切片

1、指针

指针这个东西,C中就有,指针就是存放变量在内存中的地址。

go语言中,指针不能运算,指针运算会报错。(PS:我觉得这点非常棒,我写C的时候有的时候也避免进行指针运算,不然容易出错,虽然指针运算也很方便,但是我是能不用就不用。)

package main

import "fmt"

func main()  {
	a:=100
	fmt.Printf("%x\n",&a)    //返回a 的地址c00000a0a8
	var b *int=&a
	fmt.Println(b)          //返回 a 的地址0xc00000a0a8
	fmt.Println(&b)         //返回b的地址 0xc000006030
	fmt.Println(*b)         //返回b指向的a的值 100
        
}

复制代码

在go中,当声明了一个指针p指向的地址为NULL,则称这个指针为空指针,nil

sample1用指针交换变量

package main

import "fmt"

func swap(a,b *int)  {
	tmp:=*a
	*a=*b
	*b=tmp
}


func main()  {
	a:=100
	b:=200
	c :=&a
	d:=&b
	fmt.Println(*c,*d)
	fmt.Println("-------------------")
	swap(c,d)
	fmt.Println(*c,*d)
}
/*返回
100 200
-------------------
200 100
*/
复制代码

1.1指针数组

指针数组也就是存放指针的数组。这个东西在C中有的时候特别有用,比如说临时在栈内存中创建一个指针数组当做队列或者栈来用。

sample利用指针数组遍历元素

package main

import "fmt"

const count int =4
func main()  {
	a:=[count] string {"abc","1","1.2","五六七"}
	i:=0
	//定义指针数组
	var ptr[count]*string
	//将每个元素地址赋值给指针数组
	for i=0;i<count;i++{
		ptr[i]=&a[i]
	}
	//用指针数组遍历元素

	for i=0;i<count;i++{
		fmt.Println(*ptr[i])
	}
}

复制代码

1.2指针的指针

package main

import "fmt"

func main()  {
	a:=100    //创建一个int a=100
	p:=&a     //指针p存a的地址
	pp:=&p    //指针的指针存p的地址

	fmt.Printf("%d,%d\n",&a,a)  //打印a的地址,a的值
	fmt.Printf("%d,%d\n",p,*p)  //打印p存的地址,和p指向的值
	fmt.Printf("%d,%d,%d\n",pp,*pp,**pp) //pp是pp的地址,*pp是pp指向的指针p的地址,**pp是pp->p->a的值

}
//一次输出的结果的值
/*
824633761960,100
824633761960,100
824633745448,824633761960,100
*/

复制代码

sample定义指针和指针的指针

        a:=100
	var ptr *int       //定义一个指针
	var pptr **int     //定义一个指针的指针
	ptr=&a             //指针存放a的地址
	pptr=&ptr          //指针存放ptr的地址
	fmt.Println(pptr)  //打印ptr的地址
	fmt.Println(ptr)   //打印a的地址

复制代码

1.3参数传递

2、数组

2.1数组的定义

    var a=[length]type{element1,element2}
    var a=[2]int{1,2}
复制代码

go的数组和C中不太一样的就是C中的数组就是指针,也就是C中数组取地址会得到数组的第一个元素的地址。而go中你对数组取地址会得到整个数组元素,也因此go中无法通过指针运算来遍历数组

2.2数组的长度

go中获取数组的长度通过len()函数就可以获取了。

    var a=[2]int{2,4};
    fmt.Println(len(a))    //这里输出2

复制代码

2.3多维数组

    //创建一个三行四列的二维数组
    var a=[3][4]int 
    {
        {1,2,3,4},
        {2,3,4,5},
        {3,4,5,6}
    }
复制代码

go语言中数组是值类型。也就是说数组分配内存在栈中

3、切片重点

切片是指可变数组,有点像C++中的vector?切片结构可以理解为三个部分:1、指针ptr,指向切片的指定位置。2、长度len,切片的长度。3、容量cap,也就是切片从开始到最后的长度。slice的语法和数组很像,只是没有固定长度而已。

切片的数据结构

切片ptr指向第一个元素

//这里用C语言来实现一下slice的大致的结构体
typedef struct d{
    int *ptr;  //这里是一个指针,指向的是数组中的某一个数
    int len;   //这里是长度,切片的长度
    int cap;   //这里是切面的容量
}

复制代码

长度和容量的区别在于,长度是你存放了元素的部分,容量是你能存放多少?

切片和数组的关系,两者连定义都一样。

go-slices.png

package main

import "fmt"

func main() {
    months := []string{"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}
    fmt.Println(months)
    fmt.Println("Length:", len(months))
    fmt.Println("Capacity:", cap(months))
}
复制代码

切片项(重点)

go-slices-multiple.png

package main

import "fmt"

func main() {
    months := []string{"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}
    quarter1 := months[0:3]      //这里是切片1
    quarter2 := months[3:6]      //这里是切片2
    quarter3 := months[6:9]      //这里是切片3
    quarter4 := months[9:12]     //这里是切片4
    fmt.Println(quarter1, len(quarter1), cap(quarter1))
    fmt.Println(quarter2, len(quarter2), cap(quarter2))
    fmt.Println(quarter3, len(quarter3), cap(quarter3))
    fmt.Println(quarter4, len(quarter4), cap(quarter4))
}

复制代码

3.1切片的扩容(*)

切片的扩容可以说是非常值得关注的一个知识点。

package main

import "fmt"

func main()  {
	a:=[]int{1,3,5,7}
	fmt.Printf("lena:%d\tcapa:%d\n",len(a),cap(a))
	fmt.Println("-------------")
	b:=append(a,1,2)
	fmt.Printf("lenb:%d\tcapb:%d\n",len(b),cap(b))    //b这里扩容为原来的两倍
	c:=append(a,2,4,5,6,7)
	fmt.Printf("lenc:%d\tcapc:%d\n",len(c),cap(c))    //c这里由于扩容cap==8<len==9,所以cap==10
	d:=append(a,1,2,3,4,5,6,7)
	fmt.Printf("lend:%d\tcapd:%d\n",len(d),cap(d))   //这里和上面一样
}
/*
输出结果
lena:4	capa:4
-------------
lenb:6	capb:8     
lenc:9	capc:10
lend:11	capd:12
*/

复制代码

sample逆置数组

package main

import "fmt"

func main()  {
	a:=[]int{1,3,5,7,9}

	for i,j:=0,len(a)-1;i<j;i,j=i+1,j-1{
		a[i],a[j]=a[j],a[i]
	}
	fmt.Println(a)
}
/*
返回结果
[9 7 5 3 1]
*/
复制代码

3.2 equal

利用equal来对两个切片进行比较

func equal(x, y []string) bool {
    if len(x) != len(y) {
        return false
    }
    for i := range x {
        if x[i] != y[i] {
            return false
        }
    }
    return true
}
复制代码

切片没有自己的任何数据。它只是底层数组的一个引用。对切片所做的任何修改都将反映在底层数组中。数组是值类型,而切片是引用类型

3.3 copy和append

利用copy复制

package main

import (

	"fmt"
)

func main()  {
	a:=[]int{1,3,5,7,9}
	//b:=[]int{1,3,5,7,8}
	b:=make([]int,len(a),cap(a)*2)
	ret:=copy(b,a)
	fmt.Printf("%x,%x\n",&a,&b)
	fmt.Println(ret)
	fmt.Println(b)
}


复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享