2015-11-15 2 views
2

Цель: понимание разницы между *string и string в GolangВ чем разница между строкой * и строкой в ​​Golang?


ПОПЫТКА

func passArguments() { 
    username := flag.String("user", "root", "Username for this server") 
    flag.Parse() 
    fmt.Printf("Your username is %q.", *username) 
    fmt.Printf("Your username is %q.", username) 
} 

приводит:

Your username is "root".Your username is %!q(*string=0xc820072200) 

но когда * строка присвоенные стри нг:

bla:=*username 
fmt.Printf("Your username is %q.", bla) 

он может напечатать строку еще раз:

Your username is "root".Your username is %!q(*string=0xc8200781f0).Your username is "root". 

Вопросы

  1. Почему это * строка = строка, например! отображение: "root" против %!q(*string=0xc8200781f0)?
  2. В каких других случаях должна использоваться строка * вместо строки и почему?
  3. Почему можно назначить строку * строковой переменной, в то время как отображение строки отличается, например. отображение: "root" против %!q(*string=0xc8200781f0)?
+1

Переменные, обозначенные символом *, являются указателями или адресом в памяти (считайте его почтовым адресом, где переменная является домом). Подробнее см. Https://tour.golang.org/moretypes/1. – ti7

ответ

4

A *string является указателем на строку. Если вы не знакомы с указателями, давайте просто скажем, что это значение, которое содержит адрес другого значения, а не самого значения (это уровень косвенности).

Когда в типе используется *, он обозначает указатель на этот тип. *int - указатель на целое число. ***bool - указатель на указатель на указатель на bool.

flag.String возвращает указатель на строку потому что она может затем изменить значение строки (после вызова flag.Parse), и вы можете получить это значение с помощью оператора разыменования - то есть, при использовании * на переменном, это dereferences или возвращает значение, на которое указывает вместо значения самой переменной (которая в случае указателя будет просто адресом памяти).

Так, чтобы ответить на ваши конкретные вопросы:

  1. %q глагола в fmt пакете понимает строки (и ломтики байт), а не указатели, поэтому очевидно бред отображенные (если значение не из Ожидаемый тип для глагола соответствия - здесь %q - дисплей fmt функции %!q наряду с фактическим типом и значением, переданным)

  2. указатель на строку, очень редко используется.Строка в Go является неизменной (https://golang.org/ref/spec#String_types), поэтому в таких случаях, как flag.String, где вам нужно вернуть строку, которая позже будет изменена, вам нужно вернуть указатель на строку. Но вы не увидите этого очень часто в идиоматическом Го.

  3. Вы не назначаете *string (указатель на строку) на string. То, что вы делаете, как я упоминал ранее, является разыменованием переменной *string, извлекая ее значение string. Таким образом, вы фактически назначаете string на номер string. Попробуйте удалить * на этой строке, вы увидите сообщение об ошибке компилятора. (фактически, поскольку вы используете короткую декларацию объявления переменной, :=, вы не увидите ошибку компилятора, но ваша переменная будет объявлена ​​как указатель на строку. Попробуйте это вместо этого, чтобы лучше понять, что происходит на:

    var s string 
    s = username 
    

Это поднимет ошибку компилятора).

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