Go语言跨包读取context中存储的struct值返回nil问题排查
错误原因
Go 语言的context.WithValue在匹配键时,会同时校验键的类型和值,你当前的问题本质是两个包下的键类型不匹配:
- client包定义的
applicationState{}类型标识为client.applicationState - server包定义的
applicationState{}类型标识为server.applicationState
二者是完全独立的不同类型,用server.applicationState{}作为键自然无法查询到client.applicationState{}存入的值,因此返回nil。
修复方案
方案1:统一使用同一键类型(推荐)
为了避免键冲突同时简化调用,建议将context存取逻辑封装在定义键的包内,对外暴露方法,其他包直接调用即可:
- 调整client包代码,新增存取封装:
package client import "context" type applicationState struct{} // 包私有键,避免外部冲突 type ApplicationState struct { RequestID string RequestParameters interface{} RequestPath string } // 存入ApplicationState到context func WithApplicationState(ctx context.Context, state ApplicationState) context.Context { return context.WithValue(ctx, applicationState{}, state) } // 从context取出ApplicationState func GetApplicationState(ctx context.Context) (ApplicationState, bool) { state, ok := ctx.Value(applicationState{}).(ApplicationState) return state, ok }
- 存值侧原有代码调整为调用封装方法:
appState := ApplicationState{ RequestID: "123", RequestParameters: req, RequestPath: "abc/def", } newCtx := WithApplicationState(ctx, appState) return handler(newCtx, req)
- server包取值时直接调用client包的取值方法即可:
package server import "your_project_path/client" // 导入client包 state, ok := client.GetApplicationState(ctx) fmt.Println("values from context is:", state, ok)
方案2:直接复用已有键类型
如果不想做封装,也可以在server包直接使用client包的键类型,但注意如果client包的applicationState是首字母小写的私有类型,这个方式不可用,必须用方案1封装。
内容的提问来源于stack exchange,提问作者Rajat Singh
相关产品推荐
相关产品推荐

