真正在工作中用Go的时间不久,所以也作为新手,总结了一些常见的问题和坑

Go 中指针使用注意点

// 1.空指针反向引用不合法
package main
func main() {
var p *int = nil
*p = 0
}
// in Windows: stops only with: <exit code="-1073741819" msg="process crashed"/>
// runtime error: invalid memory address or nil pointer dereference // 2.文字或者常量引用也不合法
const i = 5
ptr := &i //error: cannot take the address of i
ptr2 := &10 //error: cannot take the address of 10

Go语言常见内置函数

sort

// sort 包
import "sort"
sort.Strings(keys)

close 用于管道通信,select 用于通信的switch

type T int
func main() {
c := make(chan T)
close(c)
} // select 用法
var c1, c2, c3 chan int
var i1, i2 int
select {
case i1 = <-c1:
fmt.Printf("received ", i1, " from c1\n")
case c2 <- i2:
fmt.Printf("sent ", i2, " to c2\n")
case i3, ok := (<-c3): // same as: i3, ok := <-c3
if ok {
fmt.Printf("received ", i3, " from c3\n")
} else {
fmt.Printf("c3 is closed\n")
}
default:
fmt.Printf("no communication\n")
}

len、cap

len 用于返回某个类型的长度或数量(字符串、数组、切片、map 和管道);

cap 是容量的意思,用于返回某个类型的最大容量(只能用于切片和 map)

new、make

new 和 make 均是用于分配内存:new 用于值类型和用户定义的类型,如自定义结构,make 用于内置引用类型(切片、map 和管道)。

它们的用法就像是函数,但是将类型作为参数:new (type)、make (type)。new (T) 分配类型 T 的零值并返回其地址,也就是指向类型 T 的指针。

它也可以被用于基本类型:v := new(int)。make (T) 返回类型 T 的初始化之后的值,因此它比 new 进行更多的工作,new () 是一个函数,不要忘记它的括号

copy、append

用于复制和连接切片

panic、recover

两者均用于错误处理机制

print、println

底层打印函数,在部署环境中建议使用 fmt 包

complex、real、imag

操作复数,使用场景不多

Go不支持函数重载

Go 语言不支持这项特性的主要原因是函数重载需要进行多余的类型匹配影响性能;没有重载意味着只是一个简单的函数调度。所以你需要给不同的函数使用不同的名字,我们通常会根据函数的特征对函数进行命名

如果需要申明一个在外部定义的函数,你只需要给出函数名与函数签名,不需要给出函数体:

func flushICache(begin, end uintptr) // implemented externally

函数也可以以申明的方式被使用,作为一个函数类型,就像:

type binOp func(int, int) int

Go的map遍历时候变量地址一直用的是同一个

最佳实践:读数据可以用key,value,写数据用地址,如果要把地址赋值给另外的map,那么需要用临时变量

  kvMap := make(map[int]int)
kvMap[0] = 100
kvMap[1] = 101
kvMap[2] = 102
kvMap[3] = 103 for k, v := range kvMap {
println(k, &k, v, &v)
} // 0 0xc000049e50 100 0xc000049e48
// 1 0xc000049e50 101 0xc000049e48
// 2 0xc000049e50 102 0xc000049e48
// 3 0xc000049e50 103 0xc000049e48

Go遍历的key,value是值,而不是地址

// Version A:
items := make([]map[int]int, 5)
for i:= range items {
items[i] = make(map[int]int, 1)
items[i][1] = 2
}
fmt.Printf("Version A: Value of items: %v\n", items) // Version B: NOT GOOD!
items2 := make([]map[int]int, 5)
for _, item := range items2 {
item = make(map[int]int, 1) // item is only a copy of the slice element.
item[1] = 2 // This 'item' will be lost on the next iteration.
}
fmt.Printf("Version B: Value of items: %v\n", items2)

应当像 A 版本那样通过索引使用切片的 map 元素。在 B 版本中获得的项只是 map 值的一个拷贝而已,所以真正的 map 元素没有得到初始化

锁和 sync 包

并发编程在大部分语言里面都会有,用来解决多个线程对临界资源的访问,经典的做法是一次只能让一个线程对共享变量进行操作。当变量被一个线程改变时 (临界区),我们为它上锁,直到这个线程执行完成并解锁后,其他线程才能访问它,Go语言的这种锁机制是通过sync包中的Mutex来实现访问的,下面是一个例子,另外在sync包中还有一个读写锁,RWMutex ,其写互斥的方法与Mutex一样,读互斥采用下面的方法

mu sync.Mutex

func update(a int) {
mu.Lock()
a = xxx
mu.Unlock()
} mu2 sync.RWMutex
mu2.RLock()
mu2.RUnlock()

吴邪,小三爷,混迹于后台,大数据,人工智能领域的小菜鸟。

更多请关注

最新文章

  1. Twproject Gantt开源甘特图功能扩展
  2. ASP.NET WebForms MapPageRoute 路由配置
  3. Nginx的第一个模块-HelloWorld
  4. 【转】当你在浏览器地址栏输入一个URL后回车,将会发生的事情?
  5. MySQL创建索引语法
  6. hdu 5779 Tower Defence
  7. java,for循环中的穷举、迭代、冒泡例题
  8. oracle 日期字段的处理
  9. [PWA] 5. Hijacking one type of request
  10. IOS数据本地存储的四种方式--
  11. 单例模式——Java EE设计模式解析与应用
  12. python大法好——ython GUI编程(Tkinter)
  13. 解决tomcat中文传输乱码问题
  14. centos6.5下编译安装mariadb-10.0.20
  15. 【Unity】12.3 Off Mesh Link组件
  16. 有限状态机(FSM)的Java 演示
  17. Luogu 1070 道路游戏
  18. github基础操作
  19. Openfiler能把标准x86/64架构的系统变成一个强大的NAS、SAN存储和IP存储网关
  20. BBS - 表、登录、文件上传、注册

热门文章

  1. Ubuntu安装部署Kafka
  2. CVPR2021 | 开放世界的目标检测
  3. 单链表(LinkedList)
  4. 15、linux文件、目录的权限及如何改变权限(root用户不受任何权限的限制)
  5. SpringCloud:Eureka 配置心跳机制
  6. XCTF_Android 黑客精神
  7. APP-SECURITY-404 组件导出漏洞复现
  8. Ubuntu命令总结
  9. 从2021强网杯的一道题学习docx文件操作
  10. C语言:九宫格