golang系列之-sync.Once
如果要实现如Singleton、Lazy Initialization模式,那么你需要了解sync.Once,它可以用于保证如:只加载一次配置文件、只初始化一次数据库连接等,此外它还可以帮助实现更好的Plugin封装
当前go版本:1.24
快速上手
以下代码展示了如何使用sync.Once实现singleton模式
1 | package main |
如果要实现如Singleton、Lazy Initialization模式,那么你需要了解sync.Once,它可以用于保证如:只加载一次配置文件、只初始化一次数据库连接等,此外它还可以帮助实现更好的Plugin封装
当前go版本:1.24
以下代码展示了如何使用sync.Once实现singleton模式
1 | package main |
map/哈希表,是golang常用的数据结构之一,也充当set数据结构的存在,相对slice要复杂很多。从1.24开始,swiss table替代noswiss成为默认实现,swiss与noswiss区别在于,swiss使用开放地址法,noswiss使用拉链法
当前go版本:1.24
swiss map的开关放在文件
src/internal/buildcfg/exp.go的函数ParseGOEXPERIMENT中
todo:文章图片待补充
1 | // table-groups是二维数组,算上slot的话是三维 |
核心数据结构包括Map、table、groupsReference、groupReference,具体如下
1 | // src/internal/runtime/maps/map.go |
map/哈希表,是golang常用的数据结构之一,也充当set数据结构的存在,相对slice要复杂很多。从1.24开始,swiss table替代noswiss成为默认实现,swiss与noswiss区别在于,swiss使用开放地址法,noswiss使用拉链法
当前go版本:1.23
todo:文章图片待补充
1 | // |
map的数据结构如下所示
1 | // src/runtime/map.go |
上面数据结构中中比较关键的是
hmap - header部份,var变量存储的也是这部份buckets - 指向一片连续内存区域,bucket数组bmap - bucket的具体实现,可以存储8个key/value对,尾部overflow是溢出bucket的指针slice/切片-动态数组,golang常用的数据结构之一,相对于数组,slice可以追加元素,在容量不足时自动扩容
当前go版本:1.24
todo:文章图片待补充
slice数据结构如下所示
1 | // src/runtime/slice.go |
其中
array - 指向一片连续内存区域的第一个元素len - 已有元素数量cap - 可容纳元素总数量slice初始化方式有三种
1 | // len=3 cap=3 |
2026.03.04更新: rootless太耗资源了,没必要,不喜欢。nerdctl要么要rootless,要么sudo,很烦,先放弃了。
以Ubuntu 24.04为例,安装nerdctl以及containerd
1 | sudo apt update && sudo apt install -y uidmap |
由于懒人安装方式跟单独安装方式bin目录不一致,配置内容会有些许差异,放在下面章节各自介绍
简单介绍下macOS当前docker运行环境的最新选择:colima,一个开源产品,使用体验与vagrant类似,感觉非常不错
根据colima官方仓库指导安装colima
1 | brew install colima |
colima默认的runtime是docker,因为k8s已经剥离了docker,只保留containerd,所以为了跟k8s保持一致,另外也不想再多安装一个软件,就选择了只用containerd
但如果你使用了docker compose,那么最好还是根据教程安装docker以及docker-compose
1 | # 拉取镜像并创建vm |
以MySQL 9以及PostgreSQL 17为例,从Web开发者的角度出发,列举两个数据库在使用方面的差异,仅介绍与CRUD依赖的操作,存储过程/主从复制暂不介绍
MySQL创建管理员账户操作如下
1 | -- 1. 创建mydb_admin管理员账户 |
PostgreSQL创建管理员账户操作如下
1 | -- 1. 创建mydb_admin管理员账户 |
记录下如何移除swift文件的头部注释
注意,zsh要在空格处添加反斜杠 \,否则无法生成正确的文件路径
以下操作可以先备份文件
修改IDETemplateMacros.plist文件,移除注释内容
1 | vi ~/Library/Developer/Xcode/UserData/IDETemplateMacros.plist |
找到FILEHEADER,将string的内容清空
进入Xcode目录
1 | cd ~/Library/Developer/Xcode/ |
添加模板No Comment Swift File.xctemplate,该模板会展示在Xcode的文件目录列表
1 | mkdir -p Templates/File Templates/MultiPlatform/Source/No Comment Swift File.xctemplate |
进入模板目录
1 | cd Templates/File Templates/MultiPlatform/Source/No Comment Swift File.xctemplate |
复制原swift file模板数据
1 | cp /Applications/Xcode.app/Contents/Developer/Library/Xcode/Templates/File Templates/MultiPlatform/Source/Swift File.xctemplate/* ./ |
修改___FILEBASENAME___.swift,将第一行头部注释部分移除
默认情况下,k8s创建的服务是无法对公网提供访问的,如果要从公网访问k8s服务,一般有三种方式,NodePort、LoadBalancer、Ingress,下面简单介绍NodePort、LoadBalancer,着重讲解Ingress
本文使用的deployment同官方教程nginx-deployment,图片是从ingress-nginx官方文档拷贝过来借用,如侵必删

如上图所示,客户端访问集群内任意机器端口30100,k8s自动将请求转发到对应的服务
1 | kubectl expose deployment nginx-deployment --type="NodePort" --port 80 |
kubectl get svc,输出如下1 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE |
外部客户端先访问集群内任意节点端口31402,然后节点会转发到与端口关联的k8s内部服务nginx-deployment。
在物理机上访问服务curl http://vm1:31402,对比在虚拟机如vm1上执行curl http://10.110.255.135,两者的输出是一致的
1 | kubectl delete svc nginx-deployment |
注意:考虑到线上一般是直接通过域名访问,如果不想在域名后还要添加端口访问服务,如www.noname.io:31402,那么还需要使用nginx/haproxy建立一个反向代理的网关进行管理
在Kubernetes官网的学习教程:wordpress中,我尝试了手动创建pv并绑定pvc,但是每次申请pvc都要手动添加pv并绑定是一件很麻烦且很容易出错的事情,官方也早就意识到这个问题,提出了动态存储分配,只需要通过storageclass即可实现
本文使用了nfs作为集群存储用于实践,线上建议考虑使用ceph等分布式文件存储系统,nfs搭建教程参考:How to Install NFS Server and Client on Ubuntu 22.04
1 | # 安装客户端 |
kustomization.yaml文件鉴于gfw的影响,建议下载github.com/kubernetes-sigs/nfs-subdir-external-provisioner仓库,并将deploy文件夹提取出来,里面主要是账户创建、角色绑定、命名空间、deployment等配置
1 | # kustomization.yaml |
1 | # namespace.yaml |