目标:了解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)
但是当*字符串被分配给字符串时:
bla:=*username
fmt.Printf("Your username is %q.", bla)
它能够再次打印字符串:
Your username is "root".Your username is %!q(*string=0xc8200781f0).Your username is "root".
问题
"root"
vs.
%!q(*string=0xc8200781f0)
? "root"
vs.
%!q(*string=0xc8200781f0)
?答案 0 :(得分:5)
*string
是指向字符串的指针。如果你不熟悉指针,那么我们只是说它是一个保存另一个值的地址的值,而不是值本身(它是一个间接的级别)。 / p>
当在类型中使用*
时,它表示指向该类型的指针。 *int
是指向整数的指针。 ***bool
是指向指向bool的指针的指针。
flag.String
返回一个指向字符串的指针,因为它可以修改字符串值(在调用flag.Parse
之后),并且您可以使用取消引用运算符检索该值 - 也就是说,当对变量使用*
时,它解除引用,或者检索指向的值而不是变量本身的值(在指针的情况下,它只是一个内存地址) )。
所以回答你的具体问题:
%q
包中的fmt
动词理解字符串(和字节切片),而不是指针,因此显示明显的乱码(当值不是预期的类型时)匹配动词 - 此处%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
这会引起编译错误。)