目的:理解Golang中*string
和string
的区别
尝试
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)
但是当 *string 被分配给一个字符串时:
bla:=*username
fmt.Printf("Your username is %q.", bla)
它能够再次打印字符串:
Your username is "root".Your username is %!q(*string=0xc8200781f0).Your username is "root".
问题
- 为什么 *string != string,例如显示:
“root”
vs.%!q(*string=0xc8200781f0)
? - 在其他什么情况下 *string 应该是 使用而不是字符串,为什么?
- 为什么可以分配一个
*string 为字符串变量,而字符串的显示不同,例如显示:
“root”
vs.%!q(*string=0xc8200781f0)
?
最佳答案
*string
是一个指向字符串的指针。如果您不熟悉指针,我们就说它是一个保存另一个值地址的值,而不是值本身(这是一种间接级别)。
当 *
用于类型时,它表示指向该类型的指针。 *int
是一个指向整数的指针。 ***bool
是指向 bool 指针的指针。
flag.String
返回一个指向字符串的指针,因为它可以修改字符串值(在调用 flag.Parse
之后)并且您可以检索该值使用取消引用运算符 - 也就是说,当在变量上使用 *
时,它取消引用它,或检索指向的值而不是变量本身的值(在指针的情况下,它只是一个内存地址)。
所以回答你的具体问题:
fmt
包中的%q
动词理解字符串(和 byte slice 段),而不是指针,因此显示明显的乱码(当一个值是不是匹配动词的预期类型 - 这里%q
-fmt
函数显示%!q
以及传递的实际类型和值)很少使用指向字符串的指针。 Go 中的字符串是不可变的 (https://golang.org/ref/spec#String_types),因此在像
flag.String
这样的情况下,您需要返回一个稍后会发生变异的字符串,您必须返回一个指向字符串的指针。但在惯用的 Go 中你不会经常看到这种情况。您没有将
*string
(指向字符串的指针)分配给string
。正如我之前提到的,您正在做的是取消引用*string
变量,提取它的string
值。因此,您实际上是将string
分配给string
。尝试删除该行上的*
,您将看到编译器错误消息。 (实际上,因为您使用的是短变量声明符号:=
,您不会看到编译器错误,但您的变量将被声明为指向字符串的指针。试试相反,为了更好地理解发生了什么:var s string s = username
这会引发编译器错误)。
关于string - Golang 中的 *string 和 string 有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33722647/