接口

  • 接口由使用者定义
  • 接口的实现是隐式的
  • 只要实现接口里的方法

接口变量有什么

  • 实现者的类型和实现者的值或指针(指针指向实现者)
  • 通常接口变量自带指针
  • 接口变量同样采用值传递,几乎不需要使用接口的指针
  • 指针接收者实现只能以指针方式使用,值接收者都可

查看接口变量

  • 表示任何类型:interface{}
  • Type Assertion
  • Type Switch

函数式编程

函数是一等公民:参数,变量,返回值都可以是函数

协程

  • 轻量级“线程”
  • 非抢占式多任务处理
  • 编译器/解释器/虚拟机层面的多任务
  • 多个协程可能在一个或多个线程上运行
  • 子程序是协程的一个特例

goroutine的定义

  • 任何函数只需加上go就能送给调度器运行
  • 不需要在定义时区分是否是异步函数
  • 调度器在合适的点进行切换
  • 使用-race来检测数据访问冲突

goroutine可能的切换点

  • I/O,select
  • 函数调用(有时)
  • channel
  • runtime.Gosched()
  • 等待锁

只是参考,不能保证切换,不能保证在其他地方不切换

channel

channel作为参数

  1. package main
  2. import (
  3. "fmt"
  4. "time"
  5. )
  6. func worker(id int, c chan int) {
  7. for {
  8. fmt.Printf("Worker %d received %c\n", id, <-c)
  9. }
  10. }
  11. func chanDemo() {
  12. var channels [10]chan int
  13. for i := 0; i < 10; i++ {
  14. channels[i] = make(chan int)
  15. go worker(i, channels[i])
  16. }
  17. for i := 0; i < 10; i++ {
  18. channels[i] <- 'a' + i
  19. }
  20. time.Sleep(10 * time.Millisecond)
  21. }
  22. func main() {
  23. chanDemo()
  24. }

channel作为返回值

  1. package main
  2. import (
  3. "fmt"
  4. "time"
  5. )
  6. func createWorker(id int) chan<- int {
  7. c := make(chan int)
  8. go func() {
  9. for {
  10. fmt.Printf("Worker %d received %c\n", id, <-c)
  11. }
  12. }()
  13. return c
  14. }
  15. func chanDemo() {
  16. var channels [10]chan<- int
  17. for i := 0; i < 10; i++ {
  18. channels[i] = createWorker(i)
  19. }
  20. for i := 0; i < 10; i++ {
  21. channels[i] <- 'a' + i
  22. }
  23. time.Sleep(10 * time.Millisecond)
  24. }
  25. func main() {
  26. chanDemo()
  27. }

结构体

值接收者: 调用时使用这个值的副本来执行

指针接收者:共享调用方法时接收者所指向的值

当你的方法想修改对象中的某些域(field)时就用指针接收者