#518 关于 CPython 的 Shannon Plan
Python 2021-05-18今天刚看到一个消息,微软资助龟叔搞了个香农计划,目标是在 4 年时间内实现将 Python 提速 5 倍,而且是无痛提升,不会导致兼容性问题。最早可以在明年发布的 3.11 中得到体现:提速至少一倍。
coding in a complicated world
今天刚看到一个消息,微软资助龟叔搞了个香农计划,目标是在 4 年时间内实现将 Python 提速 5 倍,而且是无痛提升,不会导致兼容性问题。最早可以在明年发布的 3.11 中得到体现:提速至少一倍。
抱歉,又水一篇
Python 有一个好搭档就是 C/C,Python 提供生产力,C/C 则负责效率。
这篇文章探讨 Python + Go 混合开发的可能性。
其实我说的 wiki 完全谈不上 wiki。
wiki 应该是每个读者都可以编辑的,那需要一个很复杂的控制,我做不来这个。
就是我自己整理的很多笔记而已,不过都按章节编写。
或许叫做手册更为贴切(后面就一直叫手册吧)。
我觉得自己的这个习惯很好,留下有结构的一个知识体系,也是一种对学到知识的梳理。
但最近我觉得需要作出一点调整,就像 RH 变更 CentOS 的定位,将其作为 RHEL 的上游一样,我每次整理知识结构的时候先不急着去写我的手册,先写篇博文出来,积累沉淀一下,日后再从博客中提取内容充实手册。
有两个好处:
一举两得。
抱歉,水文一篇
我公司办公环境需要用到 OpenVPN,之前允许一个账号在两处登录,现在处于安全考虑只允许一处登录了。
然后,我就不方便了,因为我办公环境有两台电脑(台式机 Windows,笔记本 Ubuntu)都需要接入 VPN。
先列一下目前最火的几个 Go 语言框架:
Gin 相比 Beego 非常轻量级,不带 ORM,不支持 Session,正则路由都不支持,需要自行实现。
最新版本 56 个 文件, 算上注释,大概七千行代码。
$ find . -name "*.go" -not -path "*_test.go" | cat | wc -l
56
$ find . -name "*.go" -not -path "*_test.go" | xargs cat | wc -l
6910
Tag | CreatedAt | ReleasedAt |
---|---|---|
v1.9.0 | 2023-02-21 | 2023-02-21 |
v1.8.2 | 2022-12-22 | 2022-12-22 |
v1.8.1 | 2022-06-06 | 2022-06-06 |
v1.8.0 | 2022-05-30 | 2022-05-30 |
v1.7.7 | 2021-11-24 | 2021-11-24 |
v1.7.6 | 2021-08-03 | 2021-11-23 |
v1.7.4 | 2021-08-03 | 2021-08-15 |
v1.7.3 | 2021-08-03 | 2021-08-03 |
v1.7.2 | 2021-05-21 | 2021-05-21 |
v1.7.1 | 2021-04-08 | 2021-04-08 |
v1.7.0 | 2021-04-08 | 2021-04-08 |
v1.6.3 | 2020-05-03 | 2020-05-03 |
v1.6.2 | 2020-03-27 | 2020-03-27 |
v1.6.1 | 2020-03-23 | 2020-03-23 |
v1.6.0 | 2020-03-22 | 2020-03-22 |
v1.5.0 | 2019-11-24 | 2019-11-28 |
v1.4.0 | 2019-05-07 | 2019-05-08 |
v1.3.0 | 2018-08-14 | 2018-08-14 |
v1.2 | 2017-07-02 | 2017-07-02 |
v1.1.4 | 2016-12-04 | 2016-12-05 |
v1.1.3 | 2016-12-03 | 2016-12-04 |
// c: *gin.Context
// func (c *gin.Context) {
// balabala...
// }
c.Request.URL.Query()
c.Param(key string) string // 路径参数
c.Params.ByName(key)
c.Query(key string) string // 查询参数
c.Request.URL.Query().Get(key)
c.GetQuery(key)
c.QueryMap(key string) map[string][]string
c.GetQueryMap(key)
c.QueryArray(key string) []string
c.GetQuery(key string) (string, bool)
c.GetQueryArray(key) 的第 0 个元素
c.GetQueryMap(key string) (map[string]string, bool)
c.GetQueryArray(key string) (values []string, ok bool)
c.PostForm(key string) string
c.PostFormMap(key string) map[string][]string
c.PostFormArray(key string) []string
c.GetPostForm(key string) (string, bool)
c.GetPostFormMap(key string) (map[string]string, bool)
c.GetPostFormArray(key string) (values []string, ok bool)
c.FormFile(key string) (*multipart.FileHeader, error)
c.DefaultQuery(key string, defaultValue string) string
c.DefaultPostForm(key string, defaultValue string) string
package main
import (
"io"
"net/http"
"os"
"path/filepath"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
// 处理 GET 请求中的 URL 参数
r.GET("/hello", func(c *gin.Context) {
name := c.Query("name")
c.String(http.StatusOK, "Hello %s!", name)
})
// 处理带路径参数的 GET 请求
r.GET("/users/:id", func(c *gin.Context) {
id := c.Param("id")
c.String(http.StatusOK, "User ID: %s", id)
})
// 处理 POST 请求中的 JSON 请求体
r.POST("/data", func(c *gin.Context) {
var json struct {
Data string `json:"data"`
}
c.BindJSON(&json)
c.JSON(http.StatusOK, gin.H{"message": "Received data: " + json.Data})
})
// 处理文件上传
r.POST("/upload", func(c *gin.Context) {
file, err := c.FormFile("file")
if err != nil {
c.String(http.StatusBadRequest, "File upload failed: %s", err.Error())
return
}
// 将上传的文件保存到服务器上
dst := filepath.Join("./uploads", file.Filename)
if err := c.SaveUploadedFile(file, dst); err != nil {
c.String(http.StatusInternalServerError, "File save failed: %s", err.Error())
return
}
c.String(http.StatusOK, "File uploaded successfully")
})
// 处理返回文件
r.GET("/download", func(c *gin.Context) {
filename := "example.txt"
filepath := "./downloads/" + filename
// 打开文件
file, err := os.Open(filepath)
if err != nil {
c.String(http.StatusInternalServerError, "Failed to open file: %s", err.Error())
return
}
defer file.Close()
// 设置响应头
c.Header("Content-Disposition", "attachment; filename="+filename)
c.Header("Content-Type", "application/octet-stream")
c.Header("Content-Transfer-Encoding", "binary")
// 将文件内容写入响应主体
_, err = io.Copy(c.Writer, file)
if err != nil {
c.String(http.StatusInternalServerError, "Failed to write file: %s", err.Error())
}
})
r.Run(":8080")
}
设置路由不存在的处理方法:
r.NoRoute(func(c *gin.Context) {
c.JSON(404, gin.H{"message": "page not found"})
})
限制请求大小:
r.MaxMultipartMemory = 10 << 20 // 10MB
// "github.com/gin-contrib/size"
r.Use(size.Check(size.MB * 10))
r.Use(requestSizeLimitMiddleware(10 << 20))
func requestSizeLimitMiddleware(maxSize int64) gin.HandlerFunc {
return func(c *gin.Context) {
if c.Request.ContentLength > maxSize {
c.AbortWithStatusJSON(413, gin.H{"message": "request entity too large"})
return
}
c.Next()
}
}