【问题标题】:Why does kubernetes internally use string pointers rather than strings?为什么 Kubernetes 内部使用的是字符串指针而不是字符串?
【发布时间】:2021-04-25 22:16:47
【问题描述】:

不仅是字符串指针,还有bool指针、int指针等

见: https://github.com/kubernetes/cli-runtime/blob/5c4694c3aa38d6f710b2e3b18598f9d83f1aae3b/pkg/genericclioptions/config_flags.go#L322-L336

似乎 golang 无法从常量池之类​​的东西中受益。

Golang

package main

import (
    "fmt"
)

func StringPtr(s string) *string {
    return &s
}

func main() {
    fmt.Println(StringPtr("")) // outputs "0x40e128"
    fmt.Println(StringPtr("")) // outputs "0x40e138"
}

Python

id("") // outputs "4459080368"
id("") // outputs "4459080368"

【问题讨论】:

    标签: go


    【解决方案1】:

    通常,在config中使用int指针而不是int的目的(如kubernetes规范)是为了区分显式零和未指定,与字符串相同 或布尔。你可以在https://book.kubebuilder.io/cronjob-tutorial/api-design.html找到这个

    【讨论】:

      【解决方案2】:

      我的猜测是这样做是为了确保配置标志的值在更改时随处更新。

      这个例子可能会有所帮助

      package main
      
      import "fmt"
      
      func stringPointer(s string) *string {
          return &s
      }
      
      type Config struct {
          String  string
          Pointer *string
      }
      
      func NewConfig() Config {
          return Config{
              String:  "default",
              Pointer: stringPointer("default"),
          }
      }
      
      var (
          config = NewConfig()
      
          String  = config.String
          Pointer = config.Pointer
      )
      
      func PrintVars() {
          fmt.Printf("config.String: %v\n", config.String)
          fmt.Printf("config.Pointer: %v\n", *config.Pointer)
          fmt.Printf("String: %v\n", String)
          fmt.Printf("Pointer: %v\n", *Pointer)
          fmt.Println("-------------------------")
      }
      
      func main() {
          PrintVars()
          config.String = "new value"
          *config.Pointer = "new value"
          PrintVars()
          String = "even newer value"
          *Pointer = "even newer value"
          PrintVars()
      }
      

      出来:

      config.String: default
      config.Pointer: default
      String: default
      Pointer: default
      -------------------------
      config.String: new value
      config.Pointer: new value
      String: default
      Pointer: new value
      -------------------------
      config.String: new value
      config.Pointer: even newer value
      String: even newer value
      Pointer: even newer value
      -------------------------
      

      【讨论】:

      • 如果你在一个 goroutine 中完成所有事情就可以了。如果您在一个 goroutine 中更新 *config.Pointer 并以您的方式在另一个 goroutine 中读取它,这就是数据竞争。您还需要有一个互斥锁以避免数据竞争。
      【解决方案3】:

      属性指针赋予属性另一个值:

      type config struct {
         PtrValue *string
         Value    string
      }
      

      指向基本类型变量的指针非常适合空字符串("")nil 值具有不同含义的情况。

      例如,命令行程序的输入参数不能保证用户提供这样的输入。指针值是区分无输入和零值输入的理想方式。

      【讨论】:

        【解决方案4】:

        要存储一个字符串,您需要 2 个字的计算机内存。其中一个指向字符串的开头,另一个包含长度。

        字符串指针只有一半大小,因为它只是一个指针,没有长度。这样可以节省内存。

        当您有 100 个指向同一个字符串的指针时,这种差异就会变得明显。然后你有 100 + 2 个字加上实际的字节数组。这当然取决于newstring 是否实习字符串。

        使用字符串指针代替字符串还有另一个用例。然后程序可以区分空字符串和根本没有字符串。尤其是在配置部分,这很有用。超时时间为 0 秒与完全没有超时时间不同。对于大多数其他配置选项,空字符串无论如何都没有意义,所以这只是开销。尽管如此,它的结构还是以这种方式为每个配置选项具有相同的结构。当您需要理解代码时,这种一致性会有所帮助。

        也可能有其他原因。也许有一些关于这个主题的项目文档。

        【讨论】:

        • A string pointer is only half the size, since it's just a pointer, without the length. 。这是对的吗?我认为字符串指针只是指向计算机内存的 2 个字,它实际上包含一个指针和一个长度
        • @SergeiKurenkov 当您有 100 个指向同一个字符串的指针时,这种差异变得明显。然后你有 100 + 2 个字加上实际的字节数组。这当然取决于newstring 是否实习字符串。
        • 除了极少数情况外,内存使用角度在所有情况下都完全不相关。它可以为您节省单个 int 的大小,每次将指针复制到相同的非驻留字符串。关于检测空字符串和未指定字符串之间差异的后一段更为相关。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-08
        • 2012-08-20
        • 2021-03-07
        相关资源
        最近更新 更多