道者编程

go基础知识(二)指针

Go 语言的取地址符是 &,变量在内存中有个地址,指针就是保存的这个地址。

1:获取变量内存地址:

package main 

import "fmt"

func main(){
	a := 10
	fmt.Printf("变量a的内存地址是:%x\n",&a)
}

2:指针

func main(){
	a := 10
	p := &a //取地址
	fmt.Println(*p) //取值
}

& 取得变量 a 的内存地址,然后通过  *  从地址中把值取出来,又叫指针取值! *  不仅可以取值,还可以修改值。

3:数组指针和指针数组

指针数组:

package main 

import "fmt"

func main(){
	var a = [4]string{"abc","def","ghi","123"}

	// string 指针数组
	var b [4]*string
	fmt.Printf("%T,%v \n",b,b) //打印类型和值

	for i := 0; i<4; i++{
		/*
		因为 b 是指针数组,所以不能直接赋值,这里赋予 a 数组地址
		执行后,b 数组保存的就是数组的元素内存地址
		*/
		b[i] = &a[i] 
	}
	fmt.Printf("%T,%v \n",b,b)

	//便利指针数组,打印数组元素值
	for _,v :=range b{
		fmt.Println(*v)
	}
}

 数组指针

package main 

import "fmt"

func main(){
	x,y,z :=1,2,3
	var a *[3]int = &[3]int{x,y,z}//数组指针

	var b [3]*int = [3]*int{&x,&y,&z}//指针数组
	fmt.Println(a,"\n",b)
}
 以上输出:

&[1 2 3]
[0xc00005e080 0xc00005e088 0xc00005e090]

func main(){
	x, y := 10, 20
    a := [...]*int{&x, &y}      //指针数组 
    b := &a                     //数组指针
    fmt.Println(a,"\n",b)
}
综合:

数组指针:指向数组地址的指针

指针数组:多个数组指针(数组有多少元素就有多少指针)

4:函数指针传值

如果函数类型定义为指针类型,那么就可以给函数传递指针。

package main 

import "fmt"

func main(){
	x,y :=1,2
	//函数为指针类型,所以传递地址
	swap(&x,&y)
}

//x和y为int的指针类型
func swap(x *int,y *int){
	fmt.Println(*x,*y) //打印值
}

值传递

package main 

import "fmt"
func add(a int)int{
	a = a+1
	return a
}

func main(){
	var x int = 3
	fmt.Println("x=",x) //这里是3

	var x1 int = add(x) // x 传到add方法中变成了4
	fmt.Println("x=",x) // 但这里还是 3
}
因为值传递是内存中复制一份,被调用的函数(这里是add)参数中发送了变化,不会导致原函数(这里是main)变量的值改变。

传递指针

package main 


import "fmt"
func add(a *int)int{
	*a = *a+1
	return *a
}


func main(){
	x :=3
	fmt.Println("x=",x) //这里是3
	add(&x) //传递地址,在add中地址赋予了新值
	fmt.Println("x=",x) //这里变成了4
}

可以看到实参原来为3,但是传递之后,实参也变成了4,这是因为两个参数的内存地址是一样的。

总结:

值传递:x的值传递给a,内存中复制了一份,这样内存中的地址是不同的,值也就不一定相同

传递指针:x 的内存地址传给了 a,这样两个变量在内存中的地址是一样的,也就是两个变量指向了内存中的一个地址,所以值也是一样的。

5:结构体方法

package main 

import "fmt"

// 定义结构体 Student
type Student struct{
	Id int
	Name string
}

/*
结构体Student中的方法See
这里有个*号,表明接受者为指针类型
*/
func (m *Student) See() {
	m.Name = "李小龙" 
	fmt.Println(m.Name)
	//这里是否发现一个问题?我们取指针的值是用 * ,但是结构体指针,我们不要*取值赋值,直接使用.
}
func main(){
	//结构体赋值
	StudentVlues := Student{Id:1,Name:"李连杰",}
	// 上面是传值,下面是传地,但都是一样的。
	// 因为接受者是指着类型,如果是传值,go内部会转换成地址
	//StudentVlues := &Student{Id:1,Name:"李连杰",}
	StudentVlues.See() //调用 See 方法
	fmt.Println(StudentVlues.Name)
}
 


最新评论:
我要评论:

看不清楚