杂记3

一.字符串拼接
1.加号连接

2.fmt.Sprintf(format string,a ...interface{})string

3.string.Join(elems []string, sep string)string

4.使用strings.Builder、bytes.Buffer(两者速度相似)或者strings.Buffer(最快)

当有大量的string需要拼接时,用strings.Builder效率最高

分析:

  • 字符串在Go语言中是不可变类型,占用内存大小是固定的
  • 使用 + 每次都会重新分配内存
  • strings.Builder,bytes.Buffer底层都是[]byte数组
  • 内存扩容策略,不需要每次拼接重新分配内存


二.byte和rune
1.string中每个元素叫“字符”,字符有两种:

byte:1个字节,代表ASCII码的一个字符

rune:4个字节,代表一个UTF-8字符,一个汉字(占3个byte长度)可用一个rune表示

2.string底层是byte数组

3.string可以转换为[]byte或[]rune类型

4.string是常量,不能修改其中的字符


三.常量(const类型)不能进行强制转换


四.二维数组初始化

第1维可以用...推测,第2维不能用...

例:var arr2 = [...][3]int{{1},{2,3}}

 

五.切片

1.(里面含指针)

 

 2.二维数组各行的列数相等,但二维切片各行的len可以不等

3.append是在len之后追加的,比如

s := make([]int, 3, 5)

==>[0, 0, 0]

s = append(s, 100)

==>[0, 0, 0, 100]

s := make([]int, 0, 5)

==>[]

s = append(s, 100)

==>[100]

  切片相对于数组最大的特点就是可以追加元素,可以自动扩容

4.截取子切片

s := make([]int, 3, 5)  //len = 3, cap = 5
sub_slice = s[1:3]       //len = 2(1,2), cap = 4(1,2,3,4)
  • 刚开始,子切片和母切片共享底层的内存空间,修改子切片会反映到母切片上,在子切片上执行append会把新元素放到母切片预留的内存空间上
  • 当子切片不断执行append,消耗完了母切片预留的内存空间,子切片跟母切片就会发生内存分离,此后两个切片没有任何关系

 5.内存泄漏问题

举个🌰来说明吧:

func foo() []int {
  arr := make([]int, 1 << 20)    
  return arr[3:7]   
}

func main() {
  arr1 := foo()
  //
     ...(假设中间这里有很长一段代码,且过程中要用到arr1)
  //    
  return
}

上面代码创建了一个 容量cap=长度len=1e20 的切片arr,但是只用到了arr[3:7],而在很长一段时间arr中占用的大量无用内存就造成了内存泄漏

 解决方法:1.像刚刚上面那种极端的例子,可以仅拷贝需要的那部分(深拷贝),拷贝完后即可释放掉占用的空间

      2.把不需要用到的置nil,例:arr容量为20,你只需要前19个元素,就把第20个元素置空释放掉(arr[19] = nil)

六.map

1.初始化

  • m = make(map[string]int)       //初始化,容量为0
  • m = make(map[string]int, 5)   //初始化,容量为5。强烈建议初始化时给一个合适的容量,减少扩容的概率
  • m = map[string]int{"语文":0,"数学":39}  //初始化时直接赋值

2.添加key:mp[“数学”] = 89

3.删除key:delete(mp, "数学")

4.value, ok := mp["A"]    //ok判断map中是否有键值为“A”的键值对

 

七.管道(通道)

  • 声明通道类型变量格式:var channel_name chan value_type;例1:var intChan chan int,例2:var arrayChan chan []bool
  • 底层实现是 环形队列
  • range遍历管道时要先close,不然会产生死锁:读到最后一个元素之后会堵塞,因为系统不排除之后还有数据要读入的可能,就会一直等在那儿造成堵塞 。

           计数for循环遍历 不用

           两者共同点:管道里被遍历到的元素都会被取出,所以当你将管道里所有的元素都遍历一遍之后,管道里也没数据了

 

八.引用类型

  • slice、map和channel是go语言里的3种引用类型,都可以通过make函数来进行初始化(申请分配内存)
  • 因为它们都包含一个指向底层数据结构的指针,所以称之为“引用”类型
  • 引用类型未初始化时都是nil,可以对它们执行len()函数,返回0
posted @ 2023-01-17 21:02  balabalahhh  阅读(11)  评论(0编辑  收藏  举报