2011-02-08 5 views
43

저는 Go로 놀아 왔으며, 가치 또는 참조에 의해 구조체가 전달 될 때 좋은 정신 모델을 아직 가지고 있지 않습니다.Go 객체의 포인터 값을 어떻게 인쇄합니까? 포인터 값은 무엇을 의미합니까?

이것은 매우 멍청한 질문 일지 모르지만 나는 단지 약간의 실험을하고 나는 여전히 같은 객체에 대해 작업하고 있는지, 아니면 사본을 만들었는지 (값으로 전달했는지) 확인하고 싶습니다.

개체의 포인터 값 (gc로 포인터 값이 변경되면 내부 ID)을 인쇄 할 수 있습니까?

0x4930d4 
from gotest: 
0x4974d8 
42 
0x4930d4 
42 

가 왜 내에서 포인터 값이 다른 값 일상적인 쇼를 이동 않습니다
package main 

import ("runtime") 

type Something struct { 
    number int 
    queue chan int 
} 

func gotest(s *Something, done chan bool) { 
    println("from gotest:") 
    println(&s) 
    for num := range s.queue { 
     println(num) 
     s.number = num 
    } 
    done <- true 
} 

func main() { 
    runtime.GOMAXPROCS(4) 
    s := new(Something) 
    println(&s) 
    s.queue = make(chan int) 
    done := make(chan bool) 
    go gotest(s, done) 
    s.queue <- 42 
    close(s.queue) 
    <- done 
    println(&s) 
    println(s.number) 
} 

은 (8g 컴파일 된 버전) 내 창에 제공? 원본 객체의 수량이 변경되어 동일한 객체로 작업하고있었습니다. 영속적 인 객체 ID를 볼 수있는 방법이 있습니까?

답변

51

이동 함수 인자는 값에 의해 전달된다.

우선, 예제의 관련성이없는 부분을 버리십시오. 그러면 값으로 인수를 전달하는 것만 알 수 있습니다. 예를 들어,

package main 

import "fmt" 

func byval(q *int) { 
    fmt.Printf("3. byval -- q %T: &q=%p q=&i=%p *q=i=%v\n", q, &q, q, *q) 
    *q = 4143 
    fmt.Printf("4. byval -- q %T: &q=%p q=&i=%p *q=i=%v\n", q, &q, q, *q) 
    q = nil 
} 

func main() { 
    i := int(42) 
    fmt.Printf("1. main -- i %T: &i=%p i=%v\n", i, &i, i) 
    p := &i 
    fmt.Printf("2. main -- p %T: &p=%p p=&i=%p *p=i=%v\n", p, &p, p, *p) 
    byval(p) 
    fmt.Printf("5. main -- p %T: &p=%p p=&i=%p *p=i=%v\n", p, &p, p, *p) 
    fmt.Printf("6. main -- i %T: &i=%p i=%v\n", i, &i, i) 
} 

출력 : 함수 main에서

1. main -- i int: &i=0xf840000040 i=42 
2. main -- p *int: &p=0xf8400000f0 p=&i=0xf840000040 *p=i=42 
3. byval -- q *int: &q=0xf8400000d8 q=&i=0xf840000040 *q=i=42 
4. byval -- q *int: &q=0xf8400000d8 q=&i=0xf840000040 *q=i=4143 
5. main -- p *int: &p=0xf8400000f0 p=&i=0xf840000040 *p=i=4143 
6. main -- i int: &i=0xf840000040 i=4143 

i 메모리 위치를 초기 값 (i) 42와 (&i) 0xf800000040에서 int 변수이다. 함수에서 main

, pint42 값 (= i*p)를 가리키는 값 (= &ip) 0xf800000040 함께 메모리 위치 (&p) 0xf8000000f0에서 int 변수에 대한 포인터이다. 함수 main에서

, byval(p)는 메모리 위치 (&q) 0xf8000000d8의 함수 byval 파라미터 q에 값 (= &ip) 메모리 위치 (&p) 0xf8000000f0의 인수 0xf800000040를 할당하는 함수를 호출한다. 즉, byval 매개 변수 q에 대해 메모리가 할당되고 mainbyval 인수 p의 값이 할당됩니다. pq의 값은 처음에는 같지만 변수 pq이 다릅니다.포인터 p (*int)의 복사 포인터 q (*int), 정수 *q (i)을 이용하여 함수 byval에서

는 새로운 4143 int 값으로 설정된다. 결국 돌아 오기 전에. 포인터 qnil (제로 값)으로 설정되며 q이 사본이기 때문에 p에는 영향을 미치지 않습니다. 함수에서 main

, p 새로운 int4143 값 (= i*p)를 가리키는 값 (= &ip) 0xf800000040 함께 메모리 위치 (&p) 0xf8000000f0에서 int 변수에 대한 포인터이다. 함수에서 main

i 메모리 위치의 최종 값 (i)와 4143 (&i) 0xf800000040에서 int 변수이다. 하여 예에서

함수 호출 gotest 인수로서 사용되는 함수는 변수 mains 함수 gotests 파라미터와 동일하지 않다. 이름은 같지만 스코프와 메모리 위치가 다른 변수입니다. 함수 매개 변수 s은 함수 호출 인수 s을 숨 깁니다. 그래서 필자는 예제에서 매개 변수 변수 인 pq을 각각 차이를 강조하기 위해 명명했습니다.

하여 예에서

(&s) 0x4930d4 함수 호출 gotest(s, done) 인수로서 사용되는 함수 main에서 변수 s의 메모리 위치의 주소이며, 0x4974d8는 함수 메모리 위치의 주소 gotest 매개 변수 s. 함수 gotest의 끝에 s = nil 매개 변수를 설정하면 main의 변수 s에 영향을 미치지 않습니다. smain이고 sgotest이며 서로 다른 메모리 위치입니다. 유형별로 &s**Something, s*Something, *sSomething입니다. &sSomething 유형의 익명 변수 (메모리 위치 주소)에 대한 포인터 인 (메모리 위치 주소) s에 대한 포인터입니다. 값의 측면에서, main.&s != gotest.&s, main.s == gotest.s, main.*s == gotest.*smain.s.number == gotest.s.number.

당신은 mkb의 현자의 조언을 가지고 println(&s)을 사용하지 말아야합니다. 예를 들어, fmt 패키지를 사용

fmt.Printf("%v %p %v\n", &s, s, *s) 

가 동일한 메모리 위치를 가리킬 때 포인터가 같은 값을 가지고, 포인터는 다른 메모리 위치를 가리킬 때 다른 값을 갖습니다.

+0

내 예제에서 gotest는 'Something'에 대한 포인터를 취해서 같은 객체를 가리키는 것으로 가정하고 명확히 말하면 이동 루틴 내부의 값을 변경하면 객체의 주 값이 변경됩니다 기능. 인쇄 된 포인터 값이 다릅니다. –

+0

@JamesDean 예에서는 포인터 값 유형을 인쇄합니다. ** 뭔가 포인터 값과 같지 않습니다. 유형 * 뭔가. 포인터를 값으로 전달하기 위해 예제를 수정했습니다. – peterSO

+0

@James Dean 포인터의 주소 (즉,'s' 포인터에 대한 포인터)를 출력했습니다. - 포인터는 값으로 전달되고,'s'의 주소는's'와 같지 않습니다. 만약 당신의 gotest 함수가'println (s)'을 쓰면 포인터 값을 출력 할 것입니다. – nos

1
type sometype struct { } 
a := sometype {} 
b := int(2) 
println("Ptr to a", &a) 
println("Ptr to b", &b) 
+4

당신은 내장에 println을 사용하지만, FMT 패키지에서 적절한 것을 사용해서는 안 : HTTP : // golang .org/doc/go_spec.html # 부트 스트랩 – mkb

5

Go에서는 인수가 값으로 전달됩니다.

package main 

import "fmt" 

type SomeStruct struct { 
    e int 
} 

// struct passed by value 
func v(v SomeStruct) { 
    fmt.Printf("v: %p %v\n", &v, v) 
    v.e = 2 
    fmt.Printf("v: %p %v\n", &v, v) 
} 

// pointer to struct passed by value 
func p(p *SomeStruct) { 
    fmt.Printf("p: %p %v\n", p, *p) 
    p.e = 2 
    fmt.Printf("p: %p %v\n", p, *p) 
} 

func main() { 
    var s SomeStruct 
    s.e = 1 
    fmt.Printf("s: %p %v\n", &s, s) 
    v(s) 
    fmt.Printf("s: %p %v\n", &s, s) 
    p(&s) 
    fmt.Printf("s: %p %v\n", &s, s) 
} 

출력 :

s: 0xf800000040 {1} 
v: 0xf8000000e0 {1} 
v: 0xf8000000e0 {2} 
s: 0xf800000040 {1} 
p: 0xf800000040 {1} 
p: 0xf800000040 {2} 
s: 0xf800000040 {2} 
+0

이것은 올바르게 보이지 않습니다. 왜 포인터를 전달할 수 없습니까? 'func f (s * SomeStruct) {' –

+0

@MattJoiner : 맞습니다. 포인터를 전달할 수 있습니다. 방법을 보여주기 위해 예제를 수정했습니다. – peterSO

+0

이 언어는 잠재적 인 잠재력이 있습니다. –

1
package main 

import "fmt" 

func zeroval(ival int) { 
    ival = 0 
} 

func zeroptr(iptr *int) { 
    *iptr = 0 
} 

func main() { 
    i := 1 
    fmt.Println("initial:", i) 
    zeroval(i) 
    fmt.Println("zeroval:", i) 
    //The &i syntax gives the memory address of i, i.e. a pointer to i. 
    zeroptr(&i) 
    fmt.Println("zeroptr:", i) 
    //Pointers can be printed too. 
    fmt.Println("pointer:", &i) 
} 

출력 :

$ go run pointers.go 
initial: 1 
zeroval: 1 
zeroptr: 0 
pointer: 0x42131100 
1

가 어떻게이 이동 객체의 포인터 값을 print합니까?

0x1040a124 

포인터 값이 무엇을 의미합니까 :에서

package main 

import (
    "fmt" 
) 

func main() { 
    a := 42 
    fmt.Println(&a) 
} 

결과?

Wikipedia에 따르면

포인터는 메모리 위치를 참조