defer
1
package mainimport ("fmt")func main() {defer_call()}func defer_call() {defer func() { fmt.Println("打印前") }()defer func() { fmt.Println("打印中") }()defer func() { fmt.Println("打印后") }()panic("触发异常")}// 后、中、前 异常
defer 关键字的实现跟go关键字很类似,不同的是它调用的是runtime.deferproc而不是runtime.newproc。
在defer出现的地方,插入了指令call runtime.deferproc,然后在函数返回之前的地方,插入指令call runtime.deferreturn。
goroutine的控制结构中,有一张表记录defer,调用runtime.deferproc时会将需要defer的表达式记录在表中,而在调用runtime.deferreturn的时候,则会依次从defer表中出栈并执行。
因此,题目最后输出顺序应该是defer 定义顺序的倒序。panic 错误并不能终止 defer 的执行。
2
func hello(i int) {fmt.Println(i)}func main() {i := 5defer hello(i)i = i + 10}
5。这个例子中,hello() 函数的参数在执行 defer 语句的时候会保存一份副本,在实际调用 hello() 函数时用,所以是 5.
函数
1
func hello() []string {return nil}func main() {h := helloif h == nil {fmt.Println("nil")} else {fmt.Println("not nil")}}
- A. nil
- B. not nil
- C. compilation error
B。这道题目里面,是将 hello() 赋值给变量 h,而不是函数的返回值,所以输出 not nil。
实现set
type inter interface{}type Set struct {m map[inter]boolsync.RWMutex}func New() *Set {return &Set{m: map[inter]bool{},}}func (s *Set) Add(item inter) {s.Lock()defer s.Unlock()s.m[item] = true}
一些简单方法控制goroutines数量
package mainimport ("fmt""math""runtime")func busi(ch chan bool, i int) {fmt.Println("go func ", i, " goroutine count = ", runtime.NumGoroutine())<-ch}func main() {//模拟用户需求业务的数量task_cnt := math.MaxInt64//task_cnt := 10ch := make(chan bool, 3)for i := 0; i < task_cnt; i++ {ch <- truego busi(ch, i)}}
channel与sync同步组合方式
package mainimport ("fmt""math""sync""runtime")var wg = sync.WaitGroup{}func busi(ch chan bool, i int) {fmt.Println("go func ", i, " goroutine count = ", runtime.NumGoroutine())<-chwg.Done()}func main() {//模拟用户需求go业务的数量task_cnt := math.MaxInt64ch := make(chan bool, 3)for i := 0; i < task_cnt; i++ {wg.Add(1)ch <- truego busi(ch, i)}wg.Wait()}
利用无缓冲channel与任务发送/执行分离方式
package mainimport ("fmt""math""sync""runtime")var wg = sync.WaitGroup{}func busi(ch chan int) {for t := range ch {fmt.Println("go task = ", t, ", goroutine count = ", runtime.NumGoroutine())wg.Done()}}func sendTask(task int, ch chan int) {wg.Add(1)ch <- task}func main() {ch := make(chan int) //无buffer channelgoCnt := 3 //启动goroutine的数量for i := 0; i < goCnt; i++ {//启动gogo busi(ch)}taskCnt := math.MaxInt64 //模拟用户需求业务的数量for t := 0; t < taskCnt; t++ {//发送任务sendTask(t, ch)}wg.Wait()}
