#66 Golang 历史回顾

2021-11-09
版本 日期 备注
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

参考资料与拓展阅读

#64 Golang: 泛型

2021-10-18

泛型就是在编码中,涉及类型的定义可以不指定具体的类型,编译器根据使用时的上下文来生成相应类型的定义。

#62 转载:Diss Golang

2021-09-06

作者可能比较喜欢 C# (C# 的特性你让我丢掉哪一个我都觉得少块肉), 对 Golang 进行了一些批评,认为其设计缺乏远见,存在很多缺陷:

Anders Hejlsberg 和 Microsoft 把最佳设计都端到眼前了,其他语言纷纷各取所需,但是 Golang 的设计者却不为所动。

#61 Golang 学习资料

2021-08-24
  1. 官方文档镜像:https://docs.studygolang.com/
  2. Golang PlayGround: https://play.golang.org/ (自动跳到 https://go.dev/play/)
  3. https://awesome-go.com/
  4. https://github.com/avelino/awesome-go
  5. https://github.com/jobbole/awesome-go-cn 中文版
  6. Go语言爱好者周刊
  7. 开源图书
  8. Go 入门指南
    《The Way to Go》中文版
  9. 高效的 Go 编程
    《Effective Go》中文版
  10. Go语言标准库
    《The Golang Standard Library by Example》中文版
  11. 极客兔兔,七天用Go从零实现系列

#60 Golang 定时任务

2021-08-23

time.Ticker

异步执行(需要程序其他部分实现阻塞)

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())
        }
    }
}

time.After

package main

import (
    "fmt"
    "time"
)

func main() {
    // 延迟 5 秒后执行任务
    select {
    case <-time.After(5 * time.Second):
        fmt.Println("执行延迟任务:", time.Now())
    }
}

time.Sleep

package main

import (
    "fmt"
    "time"
)

func main() {
    // 每隔 3 秒执行一次任务
    for {
        fmt.Println("执行定时任务:", time.Now())
        time.Sleep(3 * time.Second)
    }
}

time.AfterFunc

package main

import (
    "fmt"
    "time"
)

func main() {
    // 延迟 3 秒执行任务
    time.AfterFunc(3*time.Second, func() {
        fmt.Println("延时执行的任务:", time.Now())
    })

    // 主线程继续运行,避免程序退出
    time.Sleep(5 * time.Second)
}

#58 Beego 路由

2021-08-02

基础路由

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")

mappingMethods

映射 HTTP 方法到指定方法。

  1. 支持基础路由中提到到八种方法(Any 用星号代替,优先级最低)。
  2. 如果不指定这个参数,会映射 GET 请求到 Get 方法,以此类推。
  3. 应该不支持指定多个方法。
  4. 应该不支持重复指定方法。
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") 获取。

注解路由

  1. 2.0 开始支持,dev 模式生效
  2. 自动扫描指定目录,生成 routers/commentsRouter.go 文件
  3. CommentRouterPath 配置扫描目录
web.Include(&CMSController{})

相应的控制器需要添加这样格式的注解:

// @router /staticblock/:key [get]