string - Golang 中的 *string 和 string 有什么区别?

标签 string go

目的:理解Golang中*stringstring的区别


尝试

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".

问题

  1. 为什么 *string != string,例如显示:“root” vs. %!q(*string=0xc8200781f0)?
  2. 在其他什么情况下 *string 应该是 使用而不是字符串,为什么?
  3. 为什么可以分配一个 *string 为字符串变量,而字符串的显示不同,例如显示:“root” vs. %!q(*string=0xc8200781f0)?

最佳答案

*string 是一个指向字符串的指针。如果您不熟悉指针,我们就说它是一个保存另一个值地址的值,而不是值本身(这是一种间接级别)。

* 用于类型时,它表示指向该类型的指针。 *int 是一个指向整数的指针。 ***bool 是指向 bool 指针的指针。

flag.String 返回一个指向字符串的指针,因为它可以修改字符串值(在调用 flag.Parse 之后)并且您可以检索该值使用取消引用运算符 - 也就是说,当在变量上使用 * 时,它取消引用它,或检索指向的值而不是变量本身的值(在指针的情况下,它只是一个内存地址)。

所以回答你的具体问题:

  1. fmt 包中的 %q 动词理解字符串(和 byte slice 段),而不是指针,因此显示明显的乱码(当一个值是不是匹配动词的预期类型 - 这里 %q - fmt 函数显示 %!q 以及传递的实际类型和值)

  2. 很少使用指向字符串的指针。 Go 中的字符串是不可变的 (https://golang.org/ref/spec#String_types),因此在像 flag.String 这样的情况下,您需要返回一个稍后会发生变异的字符串,您必须返回一个指向字符串的指针。但在惯用的 Go 中你不会经常看到这种情况。

  3. 您没有将 *string(指向字符串的指针)分配给 string。正如我之前提到的,您正在做的是取消引用 *string 变量,提取它的string 值。因此,您实际上是将 string 分配给 string。尝试删除该行上的 *,您将看到编译器错误消息。 (实际上,因为您使用的是短变量声明符号 :=,您不会看到编译器错误,但您的变量将被声明为指向字符串的指针。试试相反,为了更好地理解发生了什么:

    var s string
    s = username
    

这会引发编译器错误)。

关于string - Golang 中的 *string 和 string 有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33722647/

相关文章:

python - 检查字符串是否在字符串中

c++ - C++中字符串文字的数据类型是什么?

C:启动并命名字符串数组

go - net/http Serve 方法何时返回错误?

go - 如何覆盖 Go 中的符号链接(symbolic link)?

go - 不能使用 unicode 字符作为 rune

git2go : Listing files with the latest committer and commit date

无法获取字符串数组来复制一个随机值

c++ - 如何避免构造新字符串?

xml - go中将数组编码为base64