atomic包和字符串操作|青训营笔记

98 阅读1分钟

这是我参与[第五届青训营]办学笔记创作活动的第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()
}