接口
- 接口由使用者定义
- 接口的实现是隐式的
- 只要实现接口里的方法
接口变量有什么
- 实现者的类型和实现者的值或指针(指针指向实现者)
- 通常接口变量自带指针
- 接口变量同样采用值传递,几乎不需要使用接口的指针
- 指针接收者实现只能以指针方式使用,值接收者都可
查看接口变量
- 表示任何类型:interface{}
- Type Assertion
- Type Switch
函数式编程
函数是一等公民:参数,变量,返回值都可以是函数
协程
- 轻量级“线程”
- 非抢占式多任务处理
- 编译器/解释器/虚拟机层面的多任务
- 多个协程可能在一个或多个线程上运行
- 子程序是协程的一个特例
goroutine的定义
- 任何函数只需加上go就能送给调度器运行
- 不需要在定义时区分是否是异步函数
- 调度器在合适的点进行切换
- 使用-race来检测数据访问冲突
goroutine可能的切换点
- I/O,select
- 函数调用(有时)
- channel
- runtime.Gosched()
- 等待锁
只是参考,不能保证切换,不能保证在其他地方不切换
channel
channel作为参数
package main
import (
"fmt"
"time"
)
func worker(id int, c chan int) {
for {
fmt.Printf("Worker %d received %c\n", id, <-c)
}
}
func chanDemo() {
var channels [10]chan int
for i := 0; i < 10; i++ {
channels[i] = make(chan int)
go worker(i, channels[i])
}
for i := 0; i < 10; i++ {
channels[i] <- 'a' + i
}
time.Sleep(10 * time.Millisecond)
}
func main() {
chanDemo()
}
channel作为返回值
package main
import (
"fmt"
"time"
)
func createWorker(id int) chan<- int {
c := make(chan int)
go func() {
for {
fmt.Printf("Worker %d received %c\n", id, <-c)
}
}()
return c
}
func chanDemo() {
var channels [10]chan<- int
for i := 0; i < 10; i++ {
channels[i] = createWorker(i)
}
for i := 0; i < 10; i++ {
channels[i] <- 'a' + i
}
time.Sleep(10 * time.Millisecond)
}
func main() {
chanDemo()
}
结构体
值接收者: 调用时使用这个值的副本来执行
指针接收者:共享调用方法时接收者所指向的值
当你的方法想修改对象中的某些域(field)时就用指针接收者