变量定义
1 | fn main() { |
1 | fn main() { |
用过一下Redis Client的GUI,如 Medis / rdm / Another Redis DeskTop Manager/Keylord等,始终没有形成使用偏好。直到Redis官方的可视化工具RedisInsight问世
之前都是把所有建表语句放在一个文件里,复制粘贴到Navicat中执行…
这样一张表写成一个.sql文件,其实比较明了。但初始化时怎样建这些表呢? 挨个复制粘贴太麻烦…
file:///Users/fliter/rust-in-databend/17-%E6%8E%A2%E8%AE%A8Rust%E6%99%BA%E8%83%BD%E6%8C%87%E9%92%88/%E6%8E%A2%E8%AE%A8Rust%E6%99%BA%E8%83%BD%E6%8C%87%E9%92%88.pdf
file:///Users/fliter/rust-in-databend/19-%E6%8E%A2%E8%AE%A8Rust%E6%99%BA%E8%83%BD%E6%8C%87%E9%92%88II/%E6%8E%A2%E8%AE%A8Rust%E6%99%BA%E8%83%BD%E6%8C%87%E9%92%88%202.pdf
多次被安利过tmux,实际上iterm2本身的快捷键及分屏操作已经足够强大,在此总结常用命令:
src/unsafe路径下只有unsafe.go一个文件:
1 | // Copyright 2009 The Go Authors. All rights reserved. |
只有函数的签名和类型定义,但没有实现的代码:无论是 Go(go:linkname方式) 还是汇编的代码(如byteag里面的xx就是汇编代码实现)都没有。之所以如此,是因为 unsafe 包的功能需要在层次更低的编译器层面实现,所以这个包其实是内置在编译器里面实现的,unsafe.go这个文件只是为了达到文档记录的目的。
将注释移除,其实只有以下这几个函数和类型
1 | package unsafe |
其中 ArbitraryType 类型只是为了文档记录的目的而存在,实际并没有参与到 unsafe 包的实现。这个类型代表了任意的 Go 语言表达式。
所以实际上 unsafe 包就只包含三个函数和一个类型
1 | package main |
输出: 4
X 结构体有两个字段,其中每一个都占 2 个字节,所以整个结构体占用 size(n1) + size(n2) + size(X) = 2 + 2 + 0 = 4
返回的是 offset(偏移值)
1 | package main |
输出: 0 2
1 | package main |
输出 4
为什么不是3?
由于 alignment 机制的要求,n2 的内存起始地址应该是自身大小的整数倍,也就是说它的起始地址只能是 0、2、4、6、8 等偶数,所以 n2 的起始地址没有紧接着 n1 后面,而是空出了 1 个字节。最后导致结构体 X 的大小是 4 而不是 3。机智的读者可能会想到:n1 和 n2 换个位置会怎样呢?这样一来,n2 的起始地址是 0,而 n1 的其实地址是 2,这么一来结构体 X 的大小就变成 3 了吧?答案是……不对的。原因还是因为 alignment,因为 alignment 除了要求字段的其实地址应该是自身大小的整数倍,还要求整个结构体的大小,是结构体中最大的字段的大小的整数倍,这使得结构体可以由多个内存块组成,其中每个内存块的大小都等于最大的字段的大小。可以利用这个tips来减少结构体的内存占用
1 | package main |
输出为: 24 16
上面两个结构体大小不同,是因为 First 结构体由三个大小为 8 字节的内存块组成:Sizeof(First.a) + 7 个空闲的字节 + Sizeof(First.b) + Sizeof(First.c) + 7 个空闲的字节 = 24 字节; 而 Second 结构体只包含 2 个 大小为 8 字节的内存块:Sizeof(Second.a) + Sizeof(Second.b) + 6 个空闲的字节 + Sizeof(Second.b) = 16 字节。下次定义结构体的时候可以用上这个小知识(让占空间大的类型尽可能在后面)
1 | package main |
输出为:
1 | Size of x: 32 |
这三个方法都是在编译期执行的,这意味着只要编译器没有报错,在运行时也不会有问题发生
而 unsafe.Pointer则不然,有可能会发生运行时错误
参考:
原文链接: https://dashen.tech/page/36/index.html
版权声明: 转载请注明出处.
竞态: 无任何同步保护下,并行读写同一份数据(即 同一个变量。 读写指有写的同时还有其它读或者写,都是读则不算)
多个goroutine 并发读写同一个变量,需要加锁,这应该是天经地义的常识!
没有挂载数据盘的,随便玩
挂载盘的,就比较麻烦了,要小心
重要的服务,比如taskon-server,把二进制拷进去,kill pid
2024.3.11号晚上6点多,taskon无法正常访问,但是在pod里ps -aux,以及看日志是正常的
rongyi老哥看cf和腾讯云load balance的流量,发现被DDoS攻击了
同时junjie也打电话,说攻击者在discord私聊说在发动攻击,要求索要6000-8000美刀
此篇以gin升级引发的”bug”为契机,探讨Go程序获取对方真实ip的方案。
如果我们的程序前面有代理,用remoteaddr这种方式拿到的不是对方真实的ip
Rust中Mutex和RwLock都在sync包下面,
Rust标准库中的sync包提供了很多有用的线程同步原语:
Mutex/RwLock - 用来保护共享可变/只读数据,实现互斥/读写锁功能
mpsc::Sender/Receiver - 实现线程间的 channel 通讯
Arc/Rc - 引用计数指针,用于在线程间安全共享数据
Barrier - 同步多个线程到同一点进行等待
Condvar - 条件变量,配合 Mutex 实现等待/通知机制
Once - 确保只执行初始化操作一次
atomic - 常见的原子操作如 AtomicUsize、AtomicBool 等
spin - 带有轮询锁的 Mutex 实现
Semaphore - 信号量,控制并发数量
JoinHandle - 操作其他线程的句柄
scoped_threadpool - 可轻松构建工作窃取线程池
utils - 线程名称和线程安全标记方便工具
lazy_static - 实现延迟初始化的全局静态变量
futures、tokio - 异步编程模型
在Ubuntu系统中安装tcpdump的步骤如下:
1 | sudo apt update |
相关背景:
从一个k8s集群请求另一台cvm上的服务,请求成功,但是在同一个VPC内的另一个k8s集群上面,请求cvm上的服务失败…