1、什么情况下设置runtime.GOMAXPROCS会比较好的提高速度呢?
GO默认是使用一个CPU核的,通过设置runtime.GOMAXPROCS可以设置使用多核,并不是核越多处理速度越快,要根据不同业务场景设置核数,比如:
- 适合设置多核场景:CPU密集型、并行度比较高的情景,比如多数组排序,复杂计算等。
- 不适合设置多核场景:IO密集型,读写文件、爬虫如果只是抓网页而不分析等场景。
2、sync.WaitGroup用法
WaitGroup在go语言中,用于线程同步,单从字面意思理解,wait等待的意思,group组、团队的意思,WaitGroup就是指等待一组,等待一个系列执行完成后才会继续向下执行。贴上google官方的代码:
package main
import (
"fmt"
"sync"
"net/http"
)
func main() {
var wg sync.WaitGroup
var urls = []string{
"http://www.golang.org/",
"http://www.google.com/",
"http://www.baiyuxiong.com/",
}
for _, url := range urls {
// WaitGroup增加一个计数.
wg.Add(1)
// 执行goroutine抓取网页.
go func(url string) {
// 当goroutine完成是,减少WaitGroup的计数.
defer wg.Done()
// Fetch the URL.
http.Get(url)
fmt.Println(url);
}(url)
}
// 等待所有的 HTTP 完成.
wg.Wait()
fmt.Println("over");
}
#执行结果:
http://www.baiyuxiong.com/
http://www.google.com/
http://www.golang.org/
over
从执行结果可看出:
1、取三个网址信息的时候,结果显示顺序与for循环的顺序没有必然关系。
2、三个goroutine全部执行完成后,wg.Wait()才停止等待,继续执行并打印出over字符
3、go语言的组合继承
type People struct{}
func (p *People) ShowA() {
fmt.Println("showA")
p.ShowB()
}
func (p *People) ShowB() {
fmt.Println("showB")
}
type Teacher struct {
People
}
func (t *Teacher) ShowB() {
fmt.Println("teacher showB")
}
func main() {
t := Teacher{}
t.ShowA()
}
这是Golang的组合模式,可以实现OOP的继承。 被组合的类型People所包含的方法虽然升级成了外部类型Teacher这个组合类型的方法(一定要是匿名字段),但它们的方法(ShowA())调用时接受者并没有发生变化。 此时People类型并不知道自己会被什么类型组合,当然也就无法调用方法时去使用未知的组合者Teacher类型的功能。
4、go语言select随机性
- select 中只要有一个case能return,则立刻执行。
- 当如果同一时间有多个case均能return则伪随机方式抽取任意一个执行。
- 如果没有一个case能return则可以执行”default”块。
- 单个chan如果无缓冲时,将会阻塞
5、map线程安全
线程不安全时,可能会出现:可能会出现fatal error: concurrent map read and map write
以下为map不安全的例子:
type UserAges struct {
ages map[string]int
sync.Mutex
}
func (ua *UserAges) Add(name string, age int) {
ua.Lock()
defer ua.Unlock()
ua.ages[name] = age
}
func (ua *UserAges) Get(name string) int {
if age, ok := ua.ages[name]; ok {
return age
}
return -1
}
修改后如下:
func (ua *UserAges) Get(name string) int {
ua.Lock()
defer ua.Unlock()
if age, ok := ua.ages[name]; ok {
return age
}
return -1
}
5、sync.RWMutex和sync.Mutex区别
golang中sync包实现了两种锁Mutex (互斥锁)和RWMutex(读写锁),其中RWMutex是基于Mutex实现的,只读锁的实现使用类似引用计数器的功能.
type Mutex
func (m *Mutex) Lock()
func (m *Mutex) Unlock()
type RWMutex
func (rw *RWMutex) Lock()
func (rw *RWMutex) RLock()
func (rw *RWMutex) RLocker() Locker
func (rw *RWMutex) RUnlock()
func (rw *RWMutex) Unlock()
- 其中Mutex为互斥锁,Lock()加锁,Unlock()解锁,使用Lock()加锁后,便不能再次对其进行加锁,直到利用Unlock()解锁对其解锁后,才能再次加锁.适用于读写不确定场景,即读写次数没有明显的区别,并且只允许只有一个读或者写的场景,所以该锁叶叫做全局锁.
- RWMutex是一个读写锁,该锁可以加多个读锁或者一个写锁,其经常用于读次数远远多于写次数的场景. func (rw *RWMutex) Lock() 写锁,如果在添加写锁之前已经有其他的读锁和写锁,则lock就会阻塞直到该锁可用,为确保该锁最终可用,已阻塞的 Lock 调用会从获得的锁中排除新的读取器,即写锁权限高于读锁,有写锁时优先进行写锁定.
6、type 用法
switch typevalue.(type) { case int: println("int") case string: println("string") case interface{}: println("interface") default: println("unknown") }
7、defer用法总结
- defer 后面必须跟函数。
- defer在函数结束前执行,这种结束有可能是:函数正常执行完成后、函数遇到return并执行return后,函数遇到panic。
- 执行顺序:函数内容–return–defer–panic