Go

Go escape analysis

September 20, 2023
Go, Escape Analysis
Note

The meaning of escapes to the heap is variables needs to be shared across the function stack frames [between main() and Println()] … … So globally access variables must be moved to heap as it requires runtime. So the output line 11:2 shows the same as the data variable moved to the heap memory. From

Vscode go cannot find GOROOT directory

September 13, 2023
Go, Vscode
Mark

今天发现在windows上的vscode一直提示找不到go:go: cannot find GOROOT directory: c:\msys64\mingw64\lib\go。 强制设置了go.goroot也不行,直到查看了GOENV文件(C:\Users\xxx\AppData\Roaming\go\env)之后,才发现里面有一行:GOROOT=c:\msys64\mingw64\lib\go,可能是当时在msys2安装go的时候加上的。 去掉它就恢复正常了。 $ go env set GOENV=C:\Users\xxx\AppData\Roaming\go\env set GOHOSTARCH=amd64 set GOHOSTOS=windows set GOMODCACHE=C:\Users\xxx\go\pkg\mod set GOOS=windows set GOPATH=C:\Users\xxx\go set GOPRIVATE= set GOPROXY=https://goproxy.cn,https://goproxy.io,direct set GOROOT=C:\Program Files\Go 应该是这样的,如果用go env -w 来设置goroot,那么这个值就会保存到GOENV对应的文件里,如果是$env:GOROOT=xxx的方式来设置则不会修改GOENV文件里的内容。这时候,如果vscode是优先从GOENV文件来获取GOROOT的话,就可能会导致与实际的GOROOT不一致。 所以,如果再遇到以上错误,除了echo $env:GOROOT 看一下环境变量值之外,也要看一下GOENV文件。

不同系统之间通过网络对接

September 13, 2023
Go, Vscode
Mark

不同系统之间通过网络对接 数据库事件 # 可以用个事件表来做,在事务执行过程中添加事件(确保事务完成时事件也存在)。 在事务提交之后,先尝试做一次事件,如果成功了就把事件状态置为成功;如果失败了也没关系,另外开定时器来扫表进行重试执行。 – 此时不影响正常业务执行 在事件处理事务里的网络请求里加入超时控制,确保事件不会执行太久,导致接口过慢。 网络请求支持幂等,防止事件处理事务请求成功了,但是事务挂了导致状态未变更,这种情况下会重复请求多次。 skip locked实现 # -- 条件字段必须有索引(status, [name, status]),排序字段必须是主键(id),此时刚好是所要锁定的行 start transaction; -- select * from w_event we where status in (1) order by create_time asc limit 1 for update skip locked; -- 引入create_time作为排序字段时,会将符合条件的行都锁住,`limit 1`不起作用 select * from w_event we where status in (1) order by id asc limit 1 for update skip locked; -- 使用主键字段作排序时,`limit 1`则起作用 select * from w_event we where name = '测试' and status in (1) order by id asc limit 1 for update skip locked; -- 如果有多个字段作为条件,需要建立组合索引 SELECT object_name, index_name, lock_type, lock_mode, lock_data FROM performance_schema. ...

Go Empty Struct

September 1, 2023
Go
Mark

package main import ( "fmt" "unsafe" ) func main() { type A struct{} type B struct{} // 结构体里的字段都是`Empty Struct`时,占用空间为0 type S struct { A A B B } var s S fmt.Println(unsafe.Sizeof(s)) // prints 0 // 如果是指针,占用空间为8 fmt.Println(unsafe.Sizeof(&s)) // prints 8 var x [1000000000]struct{} // 可以同时存储A和B类型元素 x[0] = A{} x[1] = B{} fmt.Println(unsafe.Sizeof(x)) // prints 0 // 地址一样 fmt.Printf("%p, %p", &x[0], &x[1]) // 0x54e3a0, 0x54e3a0 } See also

NATS

April 24, 2023
Go, NATS
NATS

是什么? # Home, Github NATS 是一个简单、安全和高性能的通信系统,适用于数字系统、服务和设备。 NATS 是一种允许以消息形式分段的数据交换的基础架构。 基于主题 # 发布者将消息发到主题;订阅者订阅主题,在有消息到来时消费该消息。 主题命名规则: 基本字符:a to z, A to Z and 0 to 9 (区分大小写,不能包含空白字符). 特殊字符: . (分割符,分割不同部分,每部分视为一个token); * 和 > (通配符,*表示匹配一个token,>表示匹配一或多个token). 保留主题名称: 以 $ 开头的用在系统内部 (如:$SYS, $JS, $KV …) 发布-订阅 # Core NATS: 一个主题,存在一个发布者,多个订阅者。 消息会复制到多个订阅者。 请求-响应 # A request is sent, and the application either waits on the response with a certain timeout, or receives a response asynchronously. – 请求发出后,应用要不等待响应超时,要不就异步收到一个响应。 ...

Go Generic Join

January 6, 2023
Go, Generic, Join
Join

// NestedJoin like nested loop join func NestedJoin[J, K, R any]( left []J, right []K, match func(J, K) bool, mapper func(J, K) R, ) []R { var r = make([]R, 0, len(left)) for _, j := range left { for _, k := range right { if !match(j, k) { continue } r = append(r, mapper(j, k)) } } return r } // HashJoin like hash join func HashJoin[K comparable, LE, RE, R any]( left []LE, right []RE, lk func(item LE) K, rk func(item RE) K, mapper func(LE, RE) R, ) []R { var r = make([]R, 0, len(left)) rm := KeyBy(right, rk) for _, le := range left { k := lk(le) re := rm[k] r = append(r, mapper(le, re)) } return r } Code From

泛型

May 30, 2022
Go, TypeScript
Generic

泛型 # 是什么? # Type parameter, 类型参数。func Add[T Number](x, y T) (r T),其中的T就是类型参数,它被接口Number所约束。 type Number interface { int | float32 } 调用方除了可自行决定参数值之外,还可以自行决定参数类型。Add[int](1, 2),在调用时指定T的类型为int,同时传入参数值1,2必须是int类型。 这样使得代码更灵活,更有扩展性,同时更安全。 Go泛型 # 为什么? # 静态语言,类型固定,比如这个函数:func Add(x, y int) int就要求参数和结果都必须是整型。 那如果后来又需要一个浮点数的加法呢? 那使用interface{}不也可以吗? 试看: // 准确的描述出了参数和返回值的类型,非常方便 func Add(x, y int) int // 但也限制了Add函数的参数类型--只能接收`int` // Add(0.1, 0.2) // can't do that // 那怎么办呢?再写一个针对float64的呗 func AddFloat64(x, y float64) float64 AddFloat64(0.1, 0.2) // it's ok // 如果还要支持其它类型呢?再加一个吗,每多一种类型,就多加一个。。。 func AddInt8(x, y int8) int8 func AddInt32(x, y int32) int32 func AddFloat32(x, y float32) float32 // more. ...

Find out which Go version built your binary

May 27, 2022
Go
Version

根据二进制文件找出应用构建时使用的Go版本 # 使用 dlv: dlv exec ./app > p runtime.buildVerion 或者,在代码里调用runtime.Version(): func main() { fmt.Println("go version:", runtime.Version()) } 参照

Go enum

May 12, 2022
Go
Enum

Go enum # Go是没有内置枚举类型的,那么,当需要使用枚举时,该怎么办呢? 枚举说白了,就是一连串互斥的值,每个值代表一样事物或一个类型。 比如,现在需要一个颜色枚举,可以这样定义: const ( Red = "Red" // 红色 Blue = "Blue" // 蓝色 Green = "Green" // 绿色 ) 也有这样定义的: type Color string // 定义一个特定类型 // 枚举常量均声明为该类型 const ( Red Color = "Red" // 红色 Blue Color = "Blue" // 蓝色 Green Color = "Green" // 绿色 ) 这样做的好处是可以通过这个类型来更明显的标记出枚举字段来: type Car struct { Name string Color Color // 颜色字段声明为Color类型,在阅读代码的时候就能知道这个字段正常的可选值范围 } 但是,上面的做法都需要面临一个问题,就是我需要一个返回全部枚举值的集合时,需要这样做: func All() []Color { return []Color{ Red, Blue, Green, } } func (color Color) Name() string { switch color { case Red: return "红色" case Blue: return "蓝色" case Green: return "绿色" } return "" } 当在定义处新增值时,All和Name也要同步添加,对于开发人员来说,非常容易遗漏。 ...

Go1.18 comparable

April 22, 2022
Go
Comparable

Go 1.18 预定义接口类型 # 先看一个提案: proposal: spec: permit values to have type “comparable” – 允许值拥有comparable类型,我的理解是,现在的comparable只能用作泛型里的类型参数的约束,不能像普通类型那样使用,如下: type Set[E comparable] []E // 可以用做类型参数的约束 // 使用go1.18编译,报错:interface is (or embeds) comparable var A comparable // 变量不可以使用`comparable`类型 那么,结合例子就能更好地理解这个提案了。 这个提案的主要目的就是让例子里的var A comparable成立,也就是允许comparable作为变量的类型,跟其它普通的接口类型(var E error)一样。 // proposal: spec: permit values to have type "comparable" // As part of adding generics, Go 1.18 introduces a new predeclared interface type comparable. That interface type is implemented by any non-interface type that is comparable, and by any interface type that is or embeds comparable. ...