这是我参与[第五届青训营]办学笔记创作活动的第4天
atomic包
atomic和mutex atomic不需要进行上锁开锁的过程,就可以进行协程通信通道资源的并行操作的保证
type atomicCounter struct {
i int32
}
func AtomicAddOne(c *atomicCounter) {
atomic.AddInt32(&c.i, 1)
}
type mutexCounter struct {
i int32
m sync.Mutext
}
func MutexAddOne(c *mutexCounter) {
c.m.Lock()
c.i++
c.m.Unlock()
}
在go语言中,空结构体不占据内存
- 可作为各种场景下的占位符使用
- 节省资源
- 空结构体本身具备很强的语义,即这里不需要任何值,仅作为占位符
func EmptyStructMap(n int) {
m := make(map[int]struct{})
for i := 0; i < n; i++ {
m[i] = struct{}{}
}
}
func BoolMap(n int) {
m := make(map[int]bool)
for i := 0; i < n; i++ {
m[i] = false
}
}
使用strings.Builder
- 常见的字符串拼接方式
func Plus(n int, str string) string {
s := ""
for i := 0; i < n; i++ {
s += str
}
return s
}
func StrBuilder(n int, str string) string {
var builder strings.Builder
for i := 0; i < n; i++ {
builder.WriteString(str)
}
return builder.String()
}
func ByteBUffer(n int, str string) string {
buf := new(bytes.Buffer)
for i := 0; i < n; i++ {
buf.WriteString(str)
}
return buf.String()
}
-
使用+拼接性能最差,strings.BUilder, bytes.Buffer相近,strings.BUffer更快 分析
-
字符串在Go语言中是不可变类型,占用内存大小hi固定的
-
使用+每次都会重新分配内存
-
strings.BUffer, bytes.Buffer底层都是[]byte数组
-
内存扩容策略,不需要每次拼接重新分配内存
-
bytes.BUffer转化为字符串时重新申请了一块空间
-
strings.BUilder直接将底层的[]byte转换成了字符串类型返回
// To build strings more efficiently, see the strings.Builder type.
func(b *BUffer) string() string {
if b == nil {
// Special case, useful in debugging
return "<nil>"
}
return string(b.buf[b.off:])
}
// String returns the accumulated string.
func (b *Builder) String() string {
return *(*string)(unsafe.Pointer(&b.buf))
}
func PreStrBuilder(n int, str string) string {
var builder strings.Builder
builder.Grow(n * len(str))
for i := 0; i < n; i++ {
builder.WriterString(str)
}
return builder.String()
}
func PreByteBuffer(n int, str string) string {
buf := new(bytes.Buffer)
buf.Grow(n * len(str))
for i := 0; i < n; i++ {
buf.WriteString(str)
}
return buf.String()
}