golang 的不可变(Immutable)编程
不可变编程是一种编程思想。简单地说,就是对象的属性只能set一次。
ImmutableEphemeralVolume(immutable secret)
以 kubernetes
最近(2019年年底)的一个 ImmutableEphemeralVolume
为例。
我看了一下源代码,大意就是说,configmap
和 secret
在创建后不可更新。
以 secret 为例,目前(2020-04-16)secret 的定义是这样的:
// Secret holds secret data of a certain type. The total bytes of the values in // the Data field must be less than MaxSecretSize bytes. type Secret struct { metav1.TypeMeta `json:",inline"` // Standard object's metadata. // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata // +optional metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` // Immutable, if set to true, ensures that data stored in the Secret cannot // be updated (only object metadata can be modified). // If not set to true, the field can be modified at any time. // Defaulted to nil. // This is an alpha field enabled by ImmutableEphemeralVolumes feature gate. // +optional Immutable *bool `json:"immutable,omitempty" protobuf:"varint,5,opt,name=immutable"` // Data contains the secret data. Each key must consist of alphanumeric // characters, '-', '_' or '.'. The serialized form of the secret data is a // base64 encoded string, representing the arbitrary (possibly non-string) // data value here. Described in https://tools.ietf.org/html/rfc4648#section-4 // +optional Data map[string][]byte `json:"data,omitempty" protobuf:"bytes,2,rep,name=data"` // stringData allows specifying non-binary secret data in string form. // It is provided as a write-only convenience method. // All keys and values are merged into the data field on write, overwriting any existing values. // It is never output when reading from the API. // +k8s:conversion-gen=false // +optional StringData map[string]string `json:"stringData,omitempty" protobuf:"bytes,4,rep,name=stringData"` // Used to facilitate programmatic handling of secret data. // +optional Type SecretType `json:"type,omitempty" protobuf:"bytes,3,opt,name=type,casttype=SecretType"` }
其实只看
Immutable *bool `json:"immutable,omitempty"`
就可以了。可以看到,这是一个 bool 的指针。因为这个字段目前处于alpha
的阶段,所以用了 omitempty
这个标签忽略掉了。
判断是否已经注入
Secret
有个 String 方法有点意思。
简单地说就是通过反射判断字段是否已经注入。
func (this *Secret) String() string { ...... s := strings.Join([]string{`&Secret{`, `ObjectMeta:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.ObjectMeta), "ObjectMeta", "v1.ObjectMeta", 1), `&`, ``, 1) + `,`, `Data:` + mapStringForData + `,`, `Type:` + fmt.Sprintf("%v", this.Type) + `,`, `StringData:` + mapStringForStringData + `,`, `Immutable:` + valueToStringGenerated(this.Immutable) + `,`, `}`, }, "") return s }
valueToStringGenerated 方法展开是这样的:
func valueToStringGenerated(v interface{}) string { rv := reflect.ValueOf(v) if rv.IsNil() { return "nil" } pv := reflect.Indirect(rv).Interface() return fmt.Sprintf("*%v", pv) }
我简化了一下模型,写了个例子。
例子
package main import ( "fmt" "reflect" ) type Secret struct { Immutable *bool `json:"immutable,omitempty"` } func main() { s := Secret{Immutable: &[]bool{true}[0]} fmt.Println(valueToStringGenerated(s.Immutable)) // *true s = Secret{} fmt.Println(valueToStringGenerated(s.Immutable)) // nil } func valueToStringGenerated(v interface{}) string { rv := reflect.ValueOf(v) if rv.IsNil() { return "nil" } pv := reflect.Indirect(rv).Interface() return fmt.Sprintf("*%v", pv) }
结论
为 struct
增加一个字段,这个字段是一个指针。
通过反射获取 struct
的成员(比如字段),进而判断是否已经注入。
有些情况(比如string),用私有字段,struct 暴露一个单例模式的 Set 方法也行。我猜是 bool 类型比较特殊,所以 kubernetes
官方才用了 *bool
这个数据结构。
参考链接
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Java并发之显式锁和隐式锁的区别
Java并发之显式锁和隐式锁的区别 在面试的过程中有可能会问到:在Java并发编程中,锁有两种实现:使用隐式锁和使用显示锁分别是什么?两者的区别是什么?所谓的显式锁和隐式锁的区别也就是说说Synchronized(下文简称:sync)和lock(下文就用ReentrantLock来代之lock)的区别。 本文主要内容:将通过七个方面详细介绍sync和lock的区别。通过生活case中的X二代和普通人比较大家更容易理解这两者之间的区别 Java中隐式锁:synchronized;显式锁:lock sync和lock的区别 一:出身不同 从sync和lock的出身(原始的构成)来看看两者的不同。 Sync:Java中的关键字,是由JVM来维护的。是JVM层面的锁。 Lock:是JDK5以后才出现的具体的类。使用lock是调用对应的API。是API层面的锁 sync是底层是通过monitorenter进行加锁(底层是通过monitor对象来完成的,其中的wait/notify等方法也是依赖于monitor对象的。只有在同步块或者是同步方法中才可以调用wait/notify等方法的。因为只有在...
- 下一篇
参加Python培训需要掌握什么?爬虫怎么学!
Python培训选择哪家好?多年来,Python在各种流行编程语言中一直排名靠前。它几乎可以适用任何开发,它旨在提高程序员的开发效率而不在于他们编的代码。这也是为什么越来越多人选择用Python!参加Python培训需要掌握什么?今天,就跟大家讲解下:爬虫怎么学!作为零基础小白,大体上可分为三个阶段去实现,第一阶段是入门,掌握必备基础知识,比如Python基础、网络请求的基本原理等,第二阶段是模仿,跟着别人的爬虫代码学,弄懂每一行代码,熟悉主流的爬虫工具,第三阶段是自己动手,到了这个阶段你开始有自己的解题思路了,可以独立设计爬虫系统。爬虫涉及的技术包括但不限于熟练一门编程语言(这里以 Python 为例) HTML 知识、HTTP 协议的基本知识、正则表达式、数据库知识,常用抓包工具的使用、爬虫框架的使用、涉及到大规模爬虫,还需要了解分布式的概念、消息队列、常用的数据结构和算法、缓存,甚至还包括机器学习的应用,大规模的系统背后都是靠很多技术来支撑的。数据分析、挖掘、甚至是机器学习都离不开数据,而数据很多时候需要通过爬虫来获取,因此,即使把爬虫作为一门专业来学也是有很大前途的。那么是不是...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- CentOS关闭SELinux安全模块
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- 设置Eclipse缩进为4个空格,增强代码规范
- CentOS7,8上快速安装Gitea,搭建Git服务器
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Red5直播服务器,属于Java语言的直播服务器
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS7,CentOS8安装Elasticsearch6.8.6
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16