#67 Go 泛型的最新动态
Golang GoGenerics 2021-11-13Go 1.8 已经功能冻结,最后关头,类型约束(类型列表)的语法发生调整。
coding in a complicated world
Go 1.8 已经功能冻结,最后关头,类型约束(类型列表)的语法发生调整。
| 版本 | 日期 | 备注 |
|---|---|---|
| go1.17 | 2021-08-16 | |
| go1.16 | 2021-02-16 | |
| go1.15 | 2020-08-11 | |
| go1.14 | 2020-02-25 | |
| go1.13 | 2019-09-03 | Go modules 成为默认 |
| go1.12 | 2019-02-25 | |
| go1.11 | 2018-08-24 | Go modules 引入 |
| go1.10 | 2018-02-16 | |
| go1.9 | 2017-08-24 | |
| go1.8 | 2017-02-16 | |
| go1.7 | 2016-08-15 | context |
| go1.6 | 2016-02-17 | net/http 支持 HTTP/2 |
| go1.5 | 2015-08-19 | 并发 GC |
| go1.4 | 2014-12-10 | |
| go1.3 | 2014-06-18 | |
| go1.2 | 2013-12-01 | |
| go1.1 | 2013-05-13 | |
| go1 | 2012-03-28 |
泛型就是在编码中,涉及类型的定义可以不指定具体的类型,编译器根据使用时的上下文来生成相应类型的定义。
作者可能比较喜欢 C# (C# 的特性你让我丢掉哪一个我都觉得少块肉), 对 Golang 进行了一些批评,认为其设计缺乏远见,存在很多缺陷:
Anders Hejlsberg 和 Microsoft 把最佳设计都端到眼前了,其他语言纷纷各取所需,但是 Golang 的设计者却不为所动。
package main
import (
"fmt"
"time"
)
func main() {
// 创建一个每秒触发一次的定时器
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop() // 程序结束时停止定时器
// 启动一个 goroutine 执行定时任务
go func() {
for _ = range ticker.C {
// 每次定时器触发时执行任务
fmt.Printf("ticked at %v\n", time.Now())
}
}()
// 让主线程等待,以便定时任务能够执行
// 例如,等待 5 分钟后退出
time.Sleep(5 * time.Minute)
}
在主线程内的 for 循环中使用 select 来等待定时器触发。
主线程会一直阻塞在 select 语句中,直到收到定时器的触发信号。
package main
import (
"fmt"
"time"
)
func main() {
// 创建一个每秒触发一次的定时器
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop() // 程序结束时停止定时器
// 使用一个无限循环来监听定时器的信号
for {
select {
case <-ticker.C: // 当定时器触发时,执行任务
fmt.Println("执行定时任务:", time.Now())
}
}
}
package main
import (
"fmt"
"time"
)
func main() {
// 延迟 5 秒后执行任务
select {
case <-time.After(5 * time.Second):
fmt.Println("执行延迟任务:", time.Now())
}
}
package main
import (
"fmt"
"time"
)
func main() {
// 每隔 3 秒执行一次任务
for {
fmt.Println("执行定时任务:", time.Now())
time.Sleep(3 * time.Second)
}
}
package main
import (
"fmt"
"time"
)
func main() {
// 延迟 3 秒执行任务
time.AfterFunc(3*time.Second, func() {
fmt.Println("延时执行的任务:", time.Now())
})
// 主线程继续运行,避免程序退出
time.Sleep(5 * time.Second)
}
web.Get(router, web.HandleFunc)
web.Post(router, web.HandleFunc)
web.Put(router, web.HandleFunc)
web.Patch(router, web.HandleFunc)
web.Head(router, web.HandleFunc)
web.Options(router, web.HandleFunc)
web.Delete(router, web.HandleFunc)
web.Any(router, web.HandleFunc)
// func Router(rootpath string, c ControllerInterface, mappingMethods ...string) *HttpServer {
// return BeeApp.Router(rootpath, c, mappingMethods...)
// }
beego.Router("/admin", &admin.UserController{})
/:id, /?:id/:id:int, /:id:string/:id([0-9]+)/username/* => :splat 变量/username/*.* => :path 变量和 :ext 变量取变量的方式:
c.Ctx.Input.Param(":id")
映射 HTTP 方法到指定方法。
Get 方法,以此类推。web.Router("/api/food",&RestController{},"get:ListFood")
web.Router("/api/food",&RestController{},"post:CreateFood")
web.Router("/api/food",&RestController{},"put:UpdateFood")
web.Router("/api/food",&RestController{},"delete:DeleteFood")
web.Router("/api",&RestController{},"get,post:ApiFunc")
web.Router("/api/food",&RestController{},"get:ListFood;post:CreateFood;put:UpdateFood;delete:DeleteFood")
注意:控制器可以声明 URLMapping 方法,比 mapptingMethods 参数通过反射实现更加高效。
func (c *CMSController) URLMapping() {
c.Mapping("StaticBlock", c.StaticBlock)
c.Mapping("AllBlock", c.AllBlock)
}
web.AutoRouter(&controllers.ObjectController{})
URL 采用 /:controller/:method 前缀的方式,后面的部分会转化成 map 参数 (.Ctx.Input.Params)。
method 不区分大小写,对应的处理方法名首字母大写,比如 login -> Login。
注意:/system/config.json 对应到 SystemController.Config 方法,后缀通过 .Ctx.Input.Param(":ext") 获取。
routers/commentsRouter.go 文件CommentRouterPath 配置扫描目录web.Include(&CMSController{})
相应的控制器需要添加这样格式的注解:
// @router /staticblock/:key [get]