2015-03-04 6 views
3

Я изо всех сил пытаюсь понять, что происходит, когда вы возвращаете новый объект из функции в go.golang return object from function

У меня есть этот

func createPointerToInt() *int { 
    i := new(int) 
    fmt.Println(&i); 
    return i; 
} 

func main() { 
    i := createPointerToInt(); 
    fmt.Println(&i); 
} 

Значение напечатанного возвращенные

0x1040a128 
0x1040a120 

Я бы ожидать, что эти два значения одинакового. Я не понимаю, почему существует 8-байтовая разница.

В то, что я вижу, как эквивалентный код C:

int* createPointerToInt() { 
    int* i = new int; 
    printf("%#08x\n", i); 
    return i; 
} 

int main() { 
    int* r = createPointerToInt(); 
    printf("%#08x\n", r); 
    return 0; 
} 

возвращаемого адреса тот же:

0x8218008 
0x8218008 

Я пропускаю что-то стало очевидным здесь? Любые разъяснения будут очень признательны!

ответ

6

Вы печатаете адрес указателя здесь fmt.Println(&i);. Попробуйте это:

func main() { 
    i := createPointerToInt(); 
    fmt.Println(i); //--> Remove the ampersand 
} 

i является указатель, возвращаемый из createPointerToInt - в то время как &i является адресом указателя, который вы пытаетесь напечатать. Заметьте, что в вашем образце C вы правильно его печати:

printf("%#08x\n", r); 
       ^No ampersand here 
+1

A конечно же! Какой дурак, спасибо! Я должен был знать, что: PI думаю, что я запутался, так как go не требует от вас помешать указателю, когда вы используете его как функцию (* object) .function или object-> в C, поэтому я решил, что адрес быть адресом указателя, а не указателем. Благодаря! – Tom

+0

@Tom - добро пожаловать: D – Sadique

+1

Небольшое дополнение к этому, и я думаю, почему я изначально путался. если вы создаете собственный тип (введите MyType struct {}) и используйте это вместо int, когда вы используете Println, вы получаете '& {}' вывод, а не адрес. Для пользовательского объекта вы знаете, как получить адрес для печати? – Tom

2

Изменение &i в i. Вы печатаете адрес i, пока вы должны печатать значение i.

func createPointerToInt() *int { 
    i := new(int) 
    fmt.Println(i); 
    return i; 
} 

func main() { 
    i := createPointerToInt(); 
    fmt.Println(i); 
} 
+0

Сладкое спасибо, моя (глупая) ошибка, очень ценится!:) – Tom

+0

Привет, небольшое обновление для этого и одна из причин, почему я думаю, что я пытался использовать амперсанды в неправильном месте, - это использовать пользовательский объект ('type Example struct {}'), используя 'fmt.Println 'производит' & {} 'не адрес памяти. Есть ли способ заставить 'fmt.Println' преобразовывать это в адрес памяти? – Tom

0

Но как же в исходном коде адреса двух указателей (не адреса памяти указатели указывают тоже) разные?

func main() { 
    i := createPointerToInt(); 
    fmt.Println(&i); 
} 

эквивалентно:

func main() { 
    var i *int // declare variable i 
    i = createPointerToInt(); // assign value of 
           // a different i that was 
           // declared and initialized 
           // inside the function 
    fmt.Println(&i); 
} 

Edit:

Чтобы напечатать адрес структуры необходимо использовать:

fmt.Printf("%p\n", &your_struct) 

golang.org/pkg/fmt/

Например :

goplayground

+0

В исходном коде первый блок был функцией, а второй - основным вызовом этой функции. Возвращаемый адрес был локальным указателем переменной в каждом случае, а не адресом в область памяти, на которую ссылался указатель. Причина, по которой я совершил эту ошибку, в первую очередь, - это инструмент онлайн-голанга, когда вы используете собственный тип (тот, который вы создаете), и используйте это вместо int в этом примере, '& {}' печатается на консоли, а не адрес, который казался странным, и я не уверен, как заставить адрес печатать. – Tom

+0

Да, да, я действительно говорил об адресах двух указателей в исходном примере. Может быть, это слишком очевидно для большинства людей, но сначала это меня смутило. – Akavall

+0

@Tom, вам нужно использовать 'printf' для печати адреса' struct', я обновил свой ответ. – Akavall