前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >Go 中数据类型和使用注意事项

Go 中数据类型和使用注意事项

作者头像
_春华秋实
修改2025-01-22 11:06:31
修改2025-01-22 11:06:31
4400
代码可运行
举报
文章被收录于专栏:_春华秋实
运行总次数:0
代码可运行

Go 语言的数据类型

  • 布尔型:bool、1 字节l
  • 整型:int/uint、根据平台可能是 32 位或者是 64 位
  • 8 位整型:int8/uint8、1 字节
  • 字节型:byte、1 字节
  • 16 位整型:int16/uint16、2 字节
  • 浮点型:float32/float64、4/8 字节
  • 复数:complex64/complex128、8/16字节
  • 其他值类型:array、struct、string
  • 引用类型:slice、map、chan
  • 接口类型:interface
  • 函数类型:func(引用类型)

Golang 的 rune 类型

参考链接

// int32的别名,几乎在所有方面等同于int32 // 它用来区分字符值和整数值(就是用在字符串)

byte 等同于int8,常用来处理ascii字符

rune 等同于int32,常用来处理unicode或utf-8字符

Golang 的 string 类型

你不知道的 Go 之 string

  • string 类型使用的 utf8采用变长字节存储(英文字母是单字节存储,中文是3个字节存储)
  • len 会返回 string 的字节数,string 是字节的集合,for-range 时下标可能不连续
  • string 拼接,不要循坏使用 +,可以考虑使用 strings.Join 函数
代码语言:txt
复制
//获取字符个数 len([]rune(str))  utf8.RuneCountInString(str)               

Golang 的 channel 类型

使用 make 创建有无缓冲区的管道 ch1 := make(channel string,5)

使用场景:消息传递、同步异步、并发控制、结果汇总

代码语言:javascript
代码运行次数:0
复制
type hchan struct {
    qcount   uint           // 环形队列长度,即已有元素个数 ¥
    dataqsiz uint           // 环形队列容量,即可容纳元素个数 ¥
    buf      unsafe.Pointer // 环形队列地址(底层使用数组实现)¥
    elemsize uint16         // 元素大小
    closed   uint32       // 标识关闭状态(关闭时会唤醒队列里的 channel)
    elemtype *_type    // 元素类型
    sendx    uint      // 下一次写下标位置
    recvx    uint      // 下一次读下标位置
    recvq    waitq     // 读等待队列(阻塞时加到这个队列)¥
    sendq    waitq     // 写等待队列(阻塞时加到这个队列)¥
    lock     mutex          // 互斥锁 ¥
}            

阻塞场景

  1. 向无缓冲的队列写数据或者读数据
  2. 读缓冲区无数据,写缓冲区已满

panic 场景

  • 关闭已经关闭或者为 nil 的 channel
  • 向已经关闭的 channel 写数据

问题:channel 底层是怎么实现的?

  • 使用 数组 实现了一个环形队列,buf 结构
  • 使用了 lock 互斥锁保证了 channel 的线程安全
  • 读和写的等待队列,等待队列中的协程会在其他协程操作管道时被唤醒

Golang 的 slice 类型

代码语言:txt
复制
type slice struct {     
	array    unsafe.Pointer // 指向底层数组     
	len      int   	// 切片长度     
	cap      int   	// 底层数组容量 
}  

Go语言中的 slice 陷阱:如何避免常见的错误

参考链接

  1. 在函数里修改切片元素的值,原切片的值也会改变(如果在函数内发生扩容,函数外的值不会改变)
  2. 调用 append 方法追加元素,如果切片的容量不够会引起切片扩容(内存分配和性能问题)
  3. 谨慎使用多个切片共享一个数组,会出现写冲突
  4. 当切片容量小于 1024 时,以 2 倍的规则扩容,否则以 1.25 倍的规则扩容

Golang 的 Map 类型

  1. 不是线程安全的,避免并发的读写 Map,或者使用读写锁 或者 sync.map 解决这个问题
  2. 使用了链地址法解决 Hash 冲突
  3. 使用了增量扩容解决负载因子大于 6.5(键数量/Bucket数量)过高的问题
  4. 引用类型因为不能进行比较,不能当作 Map 的 key

Golang 数据类型的特点

数组:

  • 数组是值,将一个数组赋值给另一个,会拷贝所有的元素(如果你给函数传递一个数组,其将收到一个数组的拷贝,而不是它的指针)
  • 数组的大小是其类型的一部分。类型[10]int和[20]int是不同的。

切片:

切片持有对底层数组的引用,如果你将一个切片赋值给另一个,二者都将引用同一个数组(如果函数接受一个切片参数,对切片的元素所做的改动,对于调用者是可见的,好比是传递了一个底层数组的指针)

字典:

和切片类似,map持有对底层数据结构的引用。如果将map传递给函数,其对map的内容做了改变,则这 些改变对于调用者是可见的。

Golang 使用 defer 技巧

用于延迟函数的调用,常用于释放锁或其他资源

  • 多个defer出现的时候,它是一个“栈”的关系,也就是先进后出(一般写在函数开头捕获异常)
  • return 之后的语句先执行,defer 可以修改 return 的返回值
  • defer 函数的参数在执行时就已经确认了
  • 单个函数不能有过多 defer,影响执行的机制,导致效率下降

Golang panic 介绍

对于一些危险的操作,比如数组越界,会抛出 panic,提前结束程序执行,panic 的退出方式相对于 os.Exit() 比较优雅,支持使用 defer 和 recover 解决 panic

Golang recover 介绍

  • recover 必须要位于 defer 函数中
  • recover可以清除本函数产生的 panic,让上游函数以为一切正常执行

Go 变量作用域

花括号来控制变量的作用域,花括号中的变量是单独的作用域,同名变量会覆盖外层

Golang 控制结构

select 的特点

golang 提供的多路 I/O 复用机制 和 linux 的 select 机制类似

  • select 的每个 case 只能操作一个管道,根据管道的特性区分是否阻塞
    • 全部 case 都阻塞时陷入阻塞
    • 多个 case 不阻塞时,随机执行一个 case
    • 存在 default 时,永远不会阻塞
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-08-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档