1、什么情况下设置runtime.GOMAXPROCS会比较好的提高速度呢?

GO默认是使用一个CPU核的,通过设置runtime.GOMAXPROCS可以设置使用多核,并不是核越多处理速度越快,要根据不同业务场景设置核数,比如:

  1. 适合设置多核场景:CPU密集型、并行度比较高的情景,比如多数组排序,复杂计算等。
  2. 不适合设置多核场景: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随机性

  1. select 中只要有一个case能return,则立刻执行。
  2. 当如果同一时间有多个case均能return则伪随机方式抽取任意一个执行。
  3. 如果没有一个case能return则可以执行”default”块。
  4. 单个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()
  1. 其中Mutex为互斥锁,Lock()加锁,Unlock()解锁,使用Lock()加锁后,便不能再次对其进行加锁,直到利用Unlock()解锁对其解锁后,才能再次加锁.适用于读写不确定场景,即读写次数没有明显的区别,并且只允许只有一个读或者写的场景,所以该锁叶叫做全局锁.
  2. 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用法总结

  1. defer 后面必须跟函数。
  2. defer在函数结束前执行,这种结束有可能是:函数正常执行完成后、函数遇到return并执行return后,函数遇到panic。
  3. 执行顺序:函数内容–return–defer–panic