2015-12-31 4 views
4

Я изучал golang, и когда я проходил главу, описывающую Структуры, я сталкивался с различными способами инициализации структур.Основы Golang struct и новое() ключевое слово

p1 := passport{} 
var p2 passport 
p3 := passport{ 
    Photo: make([]byte, 0, 0), 
    Name: "Scott", 
    Surname: "Adam", 
    DateOfBirth: "Some time", 
} 

fmt.Printf("%s\n%s\n%s\n", p1, p2, p3) 

В то время как эти печати значения структур, как

{ } { } { Scott Adam Some time} , следующий код ниже отпечатков с амперсандом, потому что это ссылка.

pointerp1 := &p3 
fmt.Printf("%s", pointerp1) 
pointerp2 := new(passport) 
pointerp2.Name = "Anotherscott" 
fmt.Printf("%s", pointerp2) 

&{ Scott Adam Some time}&{ Anotherscott }

Пожалуйста, помогите мне с моими сомнениями.

  1. в использовании pointerp1 := &p3, pointerp1 является опорной переменной p3, который содержит фактические данные. Аналогично, какова будет фактическая переменная, которая содержит данные для pointerp2?

  2. Что было бы лучшим сценарием для использования этих разных типов инициализации?

+1

Go не имеет понятия «ссылки». Не называйте указатели «ссылки». – Volker

+1

@ Волькер Спасибо. Это произошло из моего класса Java. Я это запомню. – scott

ответ

10

new выделяет обнуленное хранилище для нового элемента или набирает текст, а затем возвращает указатель на него. Я не думаю, что это действительно имеет значение, если вы используете new против короткой декларации переменной := type{} это в основном просто предпочтение

Что касается pointer2, переменная pointer2 имеет свои собственные данные, когда вы делаете

// initializing a zeroed 'passport in memory' 
pointerp2 := new(passport) 
// setting the field Name to whatever 
pointerp2.Name = "Anotherscott" 

new Распределяет обнуленное хранилище в памяти и возвращает указатель на него, поэтому, короче говоря, новый вернет указатель на все, что вы делаете, поэтому pointerp2 возвращает &{ Anotherscott }

Вы в основном хотите использовать указатели, когда вы передаете переменную вокруг того, что вам нужно изменить (но будьте осторожны с гонками данных, используя мьютексы или каналы. Если вам нужно читать и записывать переменную из разных функций)

Обычный метод, используемый людьми вместо new просто короткий Декабре тип указателя:

blah := &passport{}

мля теперь указатель типа паспорта

Вы можете увидеть в этой детской площадке:

http://play.golang.org/p/9OuM2Kqncq

При передаче указателя вы можете изменить исходное значение. При передаче не указателя вы не можете его изменить. Это потому, что в переменные go передаются как копия. Таким образом, в функции iDontTakeAPointer он получает копию структуры тестера, затем модифицирует поле имени и затем возвращает, что ничего не делает для нас, поскольку оно изменяет копию, а не оригинал.

+0

Функция iDoTakeAPointer также получает копию указателя (но данные, на которые он указывает, точно такие же). – kopiczko

1
  1. Существует переменная, которая хранит данные.Вы можете разыменовать указатель с помощью *pointerp2 и даже присвоить его переменной (p2 := pointerp2), но эта переменная будет копией данных. То есть, модификация одного больше не влияет на другого (http://play.golang.org/p/9yRYbyvG8q).

  2. new имеет тенденцию быть менее популярным, особенно в отношении структур. Хорошее обсуждение его цели (намек: это на первом месте), а примеры использования можно найти по адресу https://softwareengineering.stackexchange.com/a/216582.

Edit: Кроме того, p1 не совсем иного рода инициализации от p3, но вместо того, чтобы присвоить значение любого из полей типа в их инициализации их нулевого значения ("" для string, nil для []byte). То же самое случилось бы для каких-либо опущенных полей:

p4 := passport{ 
    Name: "Scott", 
    Surname: "Adam", 
} 

В этом случае p4.Photo и p4.DateOfBirth все равно будет нулевым значением (nil и "" соответственно). Случай passport{} имеет место только один, где все поля опущены.

+0

@ Datsik It * prints * '[]', но его значение 'nil'; см. https://tour.golang.org/moretypes/11. Также есть хорошее обсуждение на странице https://groups.google.com/forum/#!topic/golang-nuts/vNodYyoUu9Q. TL; DR: нулевой фрагмент действует как пустой срез во многих отношениях. ["Это предполагаемое поведение и даже документированное поведение."] (Https://github.com/golang/go/issues/12780#issuecomment-144051177). –

+0

Я знаю об этом, но только для следующих новых читателей это должно понять, что, хотя они видят [], это все равно фактически ноль. Дело в том, что значение json будет иметь значение null: http://play.golang.org/p/GiQnKssZjH, даже если при отладке вы считаете, что у вас пустой кусочек – Datsik

0

Все новое ключевое слово does в основном создает экземпляр типа, который вы хотите. Однако вместо того, чтобы возвращать простое объявление типа, оно ссылается на него и возвращает адрес acutal памяти этого типа в куче процесса программы.

Смежные вопросы