真正在工做中用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
// sort 包 import "sort" sort.Strings(keys)
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 用于返回某个类型的长度或数量(字符串、数组、切片、map 和管道);数组
cap 是容量的意思,用于返回某个类型的最大容量(只能用于切片和 map)并发
new 和 make 均是用于分配内存:new 用于值类型和用户定义的类型,如自定义结构,make 用于内置引用类型(切片、map 和管道)。app
它们的用法就像是函数,可是将类型做为参数:new (type)、make (type)。new (T) 分配类型 T 的零值并返回其地址,也就是指向类型 T 的指针。函数
它也能够被用于基本类型:v := new(int)。make (T) 返回类型 T 的初始化以后的值,所以它比 new 进行更多的工做,new () 是一个函数,不要忘记它的括号性能
用于复制和链接切片大数据
二者均用于错误处理机制ui
底层打印函数,在部署环境中建议使用 fmt 包人工智能
操做复数,使用场景很少线程
Go 语言不支持这项特性的主要缘由是函数重载须要进行多余的类型匹配影响性能;没有重载意味着只是一个简单的函数调度。因此你须要给不一样的函数使用不一样的名字,咱们一般会根据函数的特征对函数进行命名
若是须要申明一个在外部定义的函数,你只须要给出函数名与函数签名,不须要给出函数体:
func flushICache(begin, end uintptr) // implemented externally
函数也能够以申明的方式被使用,做为一个函数类型,就像:
type binOp func(int, int) int
最佳实践:读数据能够用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
// 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 元素没有获得初始化
并发编程在大部分语言里面都会有,用来解决多个线程对临界资源的访问,经典的作法是一次只能让一个线程对共享变量进行操做。当变量被一个线程改变时 (临界区),咱们为它上锁,直到这个线程执行完成并解锁后,其余线程才能访问它,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()
吴邪,小三爷,混迹于后台,大数据,人工智能领域的小菜鸟。
更多请关注