V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  eudore  ›  全部回复第 1 页 / 共 9 页
回复总数  175
1  2  3  4  5  6  7  8  9  
3 天前
回复了 siesta 创建的主题 Go 编程语言 sublimetext 开发 GO 使用体验怎么样
@siesta 对 落伍了,但是完全没有任何动力去更换新编辑器,我只需要一个编辑器而已。
4 天前
回复了 siesta 创建的主题 Go 编程语言 sublimetext 开发 GO 使用体验怎么样
st 十年用户 付费用户路过。
以前学 cpp 的使用的 vs ,后来接触到 st 后一直在用,选择 st 主要什么都可以编辑,这些年遇到 go lua js sh yaml txt 都是用的 st 编辑,遇到新语言也不用换工具,以前破解时用 st 编辑一下 st 二进制就行。
st 开发 go 需要额外安装 gopls ,我的 go 代码都是用的远程 linux 环境运行,不需要 ide 一些环境设置;代码提示 gopls 可以支持,常用 api 也都记得;调试数据一般靠 log ,复杂的也有自己的工具可以把 struct 数据全部打印。
对于 go 编译 st 与 vsc 相比,都是需要 goget 安装一系列二进制工具( gopls ),st 的内置运行也比较简陋,st 的内置 git 组件是额外收费的。
不如直接用 atomic.CompareAndSwapInt32 ,原子比较设置。
1 看看 github 、stackoverflow 账号,不一定要进去看。
2 看过哪些标准库的源码? 然后挑上一两个说说原理、细节、坑。

涉及 runtime 、refelct 、sync 、net 、fmt 时就不同程度与核心特性相关联,go 数据库基本离不开标准库的 database/sql 库接口,在一些深度实践过程中可能会翻过部分开源项目的代码。

就是这个问题可能对初级不友好,高级会游刃有余,虽然能体现出技术素养,但是一般也要不到。
2025 年 11 月 6 日
回复了 shinonome 创建的主题 Go 编程语言 go 返回错误的时候, 返回的值应该可用吗
标准库有示例, 返回值和 error 同时不为空。
预发 dev->test->pre->prod
可以随便找一个 sql parser 的 ast node 作为定义,使用 yaml 描述 sql ast 。然后 yaml -> ast -> sql ,在 ast 还能自定义一些行为。
privoxy 单向打通 pod 和 svc 网络。
2025 年 9 月 11 日
回复了 fancy2020 创建的主题 iPhone 理性讨论,国行 iPhone 相较于外版有哪些缺陷?
没法上 V2EX ,整美区 id 太麻烦。
2025 年 9 月 2 日
回复了 xingheng 创建的主题 程序员 Stack Overflow 声望现在还有用吗
700 点路过 近几年都没怎么登录
部署一个 privoxy 可以单向暴露 pod 和 svc network ,然后本地配置 HTTP_PROXY 指向 privoxy 端口就好了。
2025 年 7 月 23 日
回复了 RichXu 创建的主题 程序员 用 v0 做了个 Markdown→卡片的网站,半天搞定,求反馈
好多基础语法都不支持,玩具都称不上。
2025 年 7 月 3 日
回复了 iorilu 创建的主题 程序员 最简单的图片编辑软件是什么, 求推荐
win+R 输入 mspaint
在中间件上执行 RemoveAll ,不能保证后续没有 Wrap Handler 然后再次使用了 WithContext 。
在 ParseMultipartForm 后手动执行 RemoveAll ,需要修改所有的 form 请求代码。
在 ParseMultipartForm 后启动新的 goroutine ,使用 context 到期删除,不太想使用新的 goroutine 。

对于 go http server ,如果存在使用 multipart/form-data 的请求,我们可以构造 form 请求,额外添加一个 32MB 的 file ;如果这个服务端使用了 WithContext 但是没有 limitBody ,我们爆掉他的服务端的 tmpdir 。


不想了,等 go 团队先处理。 https://github.com/golang/go/issues/74455
没想好,怎么都不完美,大致思路。

方法 1:WithContext post 执行 MultipartForm 同步,执行一次 WithContext 后未传递就将导致无效,包含第三方传递逻辑。
方法 2:在 ParseMultipartForm 后手动执行 RemoveAll ,所有 form 请求方法都需要执行,不仅仅是上传,防止其他 form 请求被攻击爆磁盘。
方法 3:在 HandlerFunc 之后执行一次 RemoveAll ,写法比较丑陋。
方法 4:BodyLimt 和 maxMemory 避免使用临时文件,BodyLimt 可能被不靠谱的原因调大,maxMemory 过大影响内存使用。
方法 5:框架层实现自定义清理。
多思考了一下,我选择方法 2 在使用 form file 后手动释放临时文件,本身是一个低频率功能,在 HandlerFunc 里面同时完成 Parse 和 RemoveAll ;而不是在 WithContext 时添加额外操作。

可能在 finshReq 执行 RemoveAll 就不是一个好的方法。

```go
func main() {
router := gin.Default()
router.Use(func(c *gin.Context) {
rr := c.Request
c.Request = c.Request.WithContext(c.Request.Context())
c.Next()

fmt.Println(rr.MultipartForm)
fmt.Println(c.Request.MultipartForm)
// fix 1
if rr.MultipartForm != c.Request.MultipartForm {
rr.MultipartForm = c.Request.MultipartForm
}
})
router.POST("/upload", func(c *gin.Context) {
c.Request.ParseMultipartForm(1<<10)
})
router.Run()
}
func main() {
router := gin.Default()
router.Use(func(c *gin.Context) {
c.Request = c.Request.WithContext(c.Request.Context())
})
router.POST("/upload", func(c *gin.Context) {
c.Request.ParseMultipartForm(1<<10)
// fix 2
c.Requset.MultipartForm.RemoveAll()
c.Requset.MultipartForm.File = nil
})
router.Run()
}
```
@zihuyishi
WithContext 后新旧两个 req 的 MultipartForm 值为 nil 不是 ptr ,旧 req 不包含新 req 初始化后 ptr ,旧 req 在 finshreq 的时没有执行清理。
属于 nethttp 缺陷,没有好的方法直接修正。

修复:将新旧 req 的 MultipartForm 值同步。

```go
router.Use(func(c *gin.Context) {
rr := c.Request
ctx := c.Request.Context()
c.Request = c.Request.WithContext(ctx)
c.Next()

fmt.Println(rr.MultipartForm)
fmt.Println(c.Request.MultipartForm)
if (rr.MultipartForm == nil) != (c.Request.MultipartForm == nil) {
rr.MultipartForm = c.Request.MultipartForm
}
})
```
1 、不用 form 格式,嫌弃数据格式麻烦,直接使用 octet-stream iocopy 写入文件。
2 、WithContext 方法比 Clone 更好,一些标准库修改 context 就是使用的 WithContext 方法。
3 、应该是你使用了什么奇奇怪怪的东西,正常情况下在 HandlerFunc 之前不会去解析 body ,建议删除内容和使用 nethttp 差异测试。
4 、无法复现不是问题。
为什么页面在加载之后还会加载 js ?不应该首次加载后加载所有 js 吗? 在更新瞬间访问导致版本不一样可以忽略,可以让 404 返回一段 js 去刷新页面。
2024 年 11 月 28 日
回复了 caola 创建的主题 Go 编程语言 怎么把全局共享修改为并发的
每次请求创建一次 proxyInfo 副本就好了,可以运行加上-race 参数测试并发问题。

或者把这些参数通过 newProxy 函数传递过去也行。

```go
func proxyRequestHandler() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
pi := &proxyInfo{}
//不是 https 的请求
if r.TLS == nil {
_, err := pi.getHostConf(getHostName(r.Host))
if err != nil {
w.WriteHeader( http.StatusBadRequest)
w.Write([]byte(err.Error()))
return
}
}

pi.requestPath = r.URL.Path
pi.requestRawQuery = r.URL.RawQuery

requestHeader := make(map[string]string)
requestHeader["Referer"] = pi.targetUrl
requestHeader["User-Agent"] = r.Header.Get("User-Agent")
requestHeader["Accept"] = r.Header.Get("Accept")
pi.requestHeader = requestHeader

//反代
proxy, err := pi.newProxy()
if err != nil {
panic(err)
}

proxy.ServeHTTP(w, r)
}
}
```
1  2  3  4  5  6  7  8  9  
关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   Solana   ·   2564 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 27ms · UTC 10:39 · PVG 18:39 · LAX 02:39 · JFK 05:39
♥ Do have faith in what you're doing.