douqianzha6213 2015-01-07 23:33
浏览 35
已采纳

了解Go中的指针

I am trying to understand how pointers work in Go. On a general level, I have little experience with pointers as I mostly use javascript.

I wrote this dummy program:

func swap(a, b *int) {
    fmt.Println("3", &a, &b)
    *a, *b = *b, *a

    fmt.Println("4", a, b)
}
func main() {
    x := 15
    y := 2

    fmt.Println("1", x, y)
    fmt.Println("2", &x, &y)
    swap(&x, &y)
    fmt.Println("5", x, y)
}

Which prints the following results:

$ go run test.go
1 15 2
2 0x208178170 0x208178178
3 0x2081ac020 0x2081ac028
4 0x208178178 0x208178170
5 2 15

I have several questions:

  1. From what I understand &x gives the address at which x is stored. To get the actual value of x, I need to use *x. Then, I don't understand why &x is of type *int. As *x and &x are both of type *int, their differences are not clear to me at all.

  2. In my swap function, what is the difference between using *a, *b = *b, *a and using a, b = b, a? Both work but I can't explain why...

  3. Why are the addresses different when printed between step 2 and 3?

  4. Why can't I just modify the address directly assigning &b to &a for example?

Many thanks for your help

  • 写回答

2条回答 默认 最新

  • dtm37893 2015-01-08 02:48
    关注

    1) It's a confusion about the language that leads you to think *x and &x are the same type. As Not_a_Golfer pointed out, the uses of * in expressions and type names are different. *x in your main() is invalid syntax, because * in an expression tries to get the value pointed to by the pointer that follows, but x is not a pointer (it's an int).

    I think you were thinking of the fact that when you take a pointer to x using &x, the character you add to the type name is * to form *int. I can see how it's confusing that &var gets you *typ rather than &typ. On the other hand, if they'd put & on the type name instead, that would be confusing in other situations. Some trickiness is inevitable, and like human languages, it may be easier to learn by using than discussion alone.

    2) Again, turns out the assumption is inaccurate: a, b = b, a swaps the pointers that the swap function looks at, but doesn't swap the values from main's perspective and the last line of output changes to 5 15 2: http://play.golang.org/p/rCXDgkZ9kG

    3) swap is printing the address of the pointer variables, not of the underlying integers. You'd print a and b to see the addresses of the integers.

    4) I'm going to assume, maybe wrongly, that you were hoping you could swap the locations that arbitrary variables point to with & syntax, as in &x, &y = &y, &x, without ever declaring pointer variables. There's some ambiguity, and if that's not what you were going for, I'm not sure if this part of the answer will help you.

    As with many "why can't I..." questions the easy out is "because they defined the language that way". But going to why it's that way a little bit, I think you're required to declare a variable as a pointer at some point (or another type implemented using pointers, like maps or slices) because pointers come with booby traps: you can do something over in one piece of code that changes other code's local variables in unexpected ways, for example. So wherever you see *int appear, it's telling you you might have to worry about (or, that you're able to use) things like nil pointers, concurrent access from multiple pieces of code, etc.

    Go is a bit more conservative about making pointer-hood explicit than other languages are: C++, for example, has the concept of "reference parameters" (int& i) where you could do your swap(x,y) with no & or pointers appearing in main. In other words, in languages with reference parameters, you might have to look at the declaration of a function to know whether it will change its arguments. That sort of behavior was a little too surprising/implicit/tricky for the Go folks to adopt.


    No getting around that all the referencing and dereferencing takes some thinking, and you might just have to work with it a while to get it; hope all this helps, though.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 unity第一人称射击小游戏,有demo,在原脚本的基础上进行修改以达到要求
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?
  • ¥15 加热介质是液体,换热器壳侧导热系数和总的导热系数怎么算
  • ¥100 嵌入式系统基于PIC16F882和热敏电阻的数字温度计
  • ¥15 cmd cl 0x000007b
  • ¥20 BAPI_PR_CHANGE how to add account assignment information for service line
  • ¥500 火焰左右视图、视差(基于双目相机)
  • ¥100 set_link_state
  • ¥15 虚幻5 UE美术毛发渲染