加入收藏 | 设为首页 | 会员中心 | 我要投稿 北几岛 (https://www.beijidao.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

第二章 go指针

发布时间:2021-05-21 06:24:10 所属栏目:大数据 来源: https://www.jb51.cc
导读:一. 指针 先来看一段代码 var a int = 2 var pa * int pa = a *pa = 3 fmt.Println(a) 这里定义了一个int类型的变量a,有定义了一个指针类型的变量pa,让pa指向了a的地址. 然后修改了pa的值,我们看看打印出来的a是什么: 结果: 3 ? 下面开始描述指针 1. 指针也

一. 指针

先来看一段代码

    var a int =2
    var pa *int
    pa = &a
    *pa = 3
    fmt.Println(a)    

这里定义了一个int类型的变量a,有定义了一个指针类型的变量pa,让pa指向了a的地址. 然后修改了pa的值,我们看看打印出来的a是什么:

结果:  3

?

下面开始描述指针

1. 指针也是一种变量,指针变量的定义方式,和普通变量的定义方式一样

2. go语言中的指针不能进行运算. 在c中,指针是可以运算的. 比如 &pa+2,这在go中是不可以的. 还是刚才的例子,我们对指针进行运算,编译就过不去

?

?

3. go语言只有值传递,没有引用传递. 如何实现go语言的引用传递呢,配合指针.

如果你想要传递一个int类型的数值,如果是直接传递过去. 那么就是值拷贝. 如果想要引用传递,那么就要把指针传递过去.

思考: go语言只有值传递. 比如,定义一个方法,然后调用它:

func test(a int) {
	a ++
}
func main() {
a := 5
test (a)
fmt.Println("a: ",a)
}

结果: a: 5

  这里main方法调用test,将a拷贝了一份传给test. 这是值传递. 那么怎么才能让值跟着发生变化呢? 我们可以配合地址使用.

func test(a *int) {
	*a ++
}

func main() {
	a := 5
	test (&a)
	fmt.Println("a: ",a)
}

结果: a: 6

  这是一个配合地址使用的值传递. 他的传递是将a的地址复制了一份,传给了test. 如下图:?

?

?

?他们最终指向的都是5. 所以,一旦test方法修改ile值,main方法中的也会随之修改

?

?那么,自定义类型是值传递还是引用传递呢?

?答案: 不一定. 如果你将一个对象Cache传递到一个函数里. 他是对这个Cache的值copy么? 不一定. 要看这个函数里面的内部结构: 看下面的例子.

例子1:

type Cache struct {
    aa int
    bb int
    cc string
}

func change(c Cache) 
    c.cc = "world"
    fmt.Println("in change,c",c)


func main() 
    // 初始化一个Cache对象
    var c = Cache{aa:1,bb:100,cc:"hello"}
    // 修改对象的值. 这里传递过去的是一个值拷贝
    change(c)
    fmt.Println(c)
}

这个例子, go语言只有值拷贝, 这是对对象的值拷贝的过程. 修改了函数体里面对象的属性,对函数外没有影响,?

结果:?

in change,c 1 100 world}
1 100 hello}

?

例子2:



func change(c *Cache)  修改对象的值. 这里传递过去的是一个值拷贝
    change(&c)
    fmt.Println(c)
}

这个例子和例1不一样的地方是,函数的参数是一个指针. go语言只有值拷贝,这里是将c的地址拷贝了一份传给了change. 这就达到了引用传递的效果,修改函数体里面的值,外面也受影响.

返回结果:?

}

例子3:


    aa int
    bb int
    cc *string  // 结构体里面有一个指针对象

    *c.cc = "world"
    fmt.Println("in change,c.aa,c.bb,*c.cc)

    // 初始化一个Cache对象
    cc := "hello"
    var c = Cache{aa:1,cc:&cc    change(c)
    fmt.Println(c.aa,*c.cc)
}

这个例子和前两个例子不同的地方是: 结构体Cache中cc是一个地址. 他不是一个变量了. 那么这个时候. change函数修改了cc的值,会怎么样呢?

结果:?

1 100 world
100 world

是的,cc是一个地址,当对象c拷贝一份到cc里面的时候,Cache中的地址变量cc 直接复制一份到change. 本身cc就是地址,所以函数内改变了cc所在地址的值,那么函数外也会改变

这就说明了,结构体传递到函数里面,到底是值传递还是引用传递呢? 和结构体内部的结构有关系.

?

?3. 用go语言实现交换两个变量的值.

?分析1:?

func change(a int,b int) {
a,b = b,a
fmt.Println("in change,a:",a,",b:",b)
}

func main() {
// 初始化一个Cache对象
a,b := 3,4
change(a,b)
fmt.Println(a,b)
}

上述方法返回值:?

in change,a: 4,b: 3
3 4

错误的原因在于,int类型是值传递,修改内容的值,对外部没影响. 所以返回的还是3,4

?

分析2: 地址传递

func change(a *int,b *int) {
fmt.Println(fmt.Println("[change---1],b))
a,a
fmt.Println("[change--2],4
fmt.Println("[main --- 1]",&a,&b)
change(&a,&b)
fmt.Println("[main --- 2]",b)
}

先来看输出结果:

[main --- 1] 0xc000096008 0xc000096010
[change---1],a: 0xc000096008,b: 0xc000096010
48 <nil>
[change--2],a: 0xc000096010,b: 0xc000096008
[main --- 2] 3 4

出乎意料,原本以为,1)">main函数最后的输出会是4,3. 我们发现,结果并不是. 也就是说,虽然传的是指针过去,但是是对指针的一个copy,? 这一点更说明了,1)">所有的变量都是值拷贝. 包括指针变量. 也是一个值拷贝

?

分析3: 改变地址的值

func change(a *int,b *int) 
    fmt.Println(fmt.Println("[change---1],b))
    *a,*b = *b,*a // 把地址的值改变了
    fmt.Println("[change--2],b)

    // 初始化一个Cache对象
    a,4
    fmt.Println("[main --- 1]",&b)
    change(&a,&b)
    fmt.Println("[main --- 2]",1)">}

和三个不同之处,是在change函数内,修改了指针类型的变量的值. 输出结果是:

[main --- 1] 0xc00001c0f8 0xc00001c100
[change---],a: 0xc00001c0f8,b: 0xc00001c100
48 <nil>
[change--22] 4 3

我们看到,最后的输出结果却是是4,3

?

分析4: 还有一种更简单的交换两个值的方式

func change(a *int,b *int) (int,int)
    return *b,*a
}

输出:

[main --- ] 0xc00001c0f8 0xc00001c100
[main --- 3

?

分析5: 最简单的方式

func change(a int,b int) (int,1)">
    return b,a
}

结果:

[main --- ] 0xc000096008 0xc000096010
[main --- 3

?

从这里我们得出以下结论:?

1. 指针类型的变量,和普通变量一样,是值传递.?

2. 指针类型的变量,要想修改变量的值,需要使用指针的指针来改变. 其实,在指针里面,是指针的指针就是值了. 那么,我们的原则是,不管他是什么,只有修改的是指针,那么就达到了引用传递的效果.

?

?

指针对于我们来说,方便好多,但是也会产生很对疑问. 比如分析4和分析5,他们为什么得到的结果是一只呢? 需要看一下他的内部到底是怎么交换的.

?

?

?

?

?

?

aaa

(编辑:北几岛)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读