如何在 Go 中正确通过指针参数初始化结构体指针变量

发布时间 - 2026-01-09 00:00:00    点击率:

go 函数参数按值传递,即使传入的是指针(如 `*mgo.session`),函数内对其赋值仅修改副本;要真正更新原始变量,必须传入指向该指针的指针(即 `**mgo.session`),并在函数内解引用赋值。

在 Go 中,所有函数参数都是按值传递的——这意味着传入函数的不是变量本身,而是它的副本。这一点对指针类型尤其容易产生误解:虽然 *T 是一个指针,但 *T 本身仍是一个值(存储着内存地址的变量),它在函数调用时也会被复制。

以原始代码为例:

func ConnectToMongo(session *mgo.Session) {
    session, err = mgo.Dial("localhost:27028") // ❌ 只修改了参数副本,不影响 main 中的 session
}

这里 session 是 *mgo.Session 类型的形参,其值(即 nil 地址)被复制进函数。后续 session = ... 只是让这个局部副本指向新地址,而 main 中的 session 变量依然为 nil。

✅ 正确做法是使用双重指针(**mgo.Session),让函数能修改原始指针变量的值:

func ConnectToMongo(session **mgo.Session) {
    if *session == nil { // 注意:此处应检查 *session,而非 session(后者是 **mgo.Session,不可能为 nil 除非传入 nil 地址)
        var err error
        *session, err = mgo.Dial("localhost:27028")
        if err != nil {
            panic(err)
        }
    }
}

func main() {
    var session *mgo.Session
    ConnectToMongo(&session) // 传入 session 变量的地址
    if session == nil {
        fmt.Println("nil. Why?") // 不会执行
    } else {
        fmt.Println("Connected successfully.")
        defer session.Close() // 记得关闭连接
    }
}

⚠️ 关键注意事项:

  • if session == nil 在 **mgo.Session 函数中是检查“指针的指针是否为空”,而非“目标指针是否为空”——逻辑错误;应改为 if *session == nil。

  • &session 获取的是 *mgo.Session 类型变量的地址,类型为 **mgo.Session,与函数签名严格匹配。

  • 现代 Go 推荐更清晰、更符合惯用法的写法:直接返回值,而非依赖多重指针副作用:

    func ConnectToMongo() (*mgo.Session, error) {
        return mgo.Dial("localhost:27028")
    }
    
    func main() {
        session, err := ConnectToMongo()
        if err != nil {
            panic(err)
        }
        defer session.Close()
    }

    这种方式语义明确、易于测试、避免隐式状态修改,是更健壮和可维护的设计。

总结:Go 中无法通过单级指针参数“输出”新对象地址;若必须使用参数输出模式,务必使用 **T 并正确解引用 *session = newValue;但优先推荐返回值方式,兼顾简洁性与安全性。


# go  # session  # ai  # if 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 百度浏览器ai对话怎么关 百度浏览器ai聊天窗口隐藏  Laravel如何使用Sanctum进行API认证?(SPA实战)  教学论文网站制作软件有哪些,写论文用什么软件 ?  黑客入侵网站服务器的常见手法有哪些?  北京网站制作的公司有哪些,北京白云观官方网站?  惠州网站建设制作推广,惠州市华视达文化传媒有限公司怎么样?  Laravel如何为API生成Swagger或OpenAPI文档  Laravel如何实现邮件验证激活账户_Laravel内置MustVerifyEmail接口配置【步骤】  香港服务器部署网站为何提示未备案?  如何彻底删除建站之星生成的Banner?  Swift中switch语句区间和元组模式匹配  什么是JavaScript解构赋值_解构赋值有哪些实用技巧  javascript事件捕获机制【深入分析IE和DOM中的事件模型】  大连企业网站制作公司,大连2025企业社保缴费网上缴费流程?  如何在宝塔面板中修改默认建站目录?  如何获取上海专业网站定制建站电话?  东莞市网站制作公司有哪些,东莞找工作用什么网站好?  如何快速配置高效服务器建站软件?  Laravel Facade的原理是什么_深入理解Laravel门面及其工作机制  详解一款开源免费的.NET文档操作组件DocX(.NET组件介绍之一)  android nfc常用标签读取总结  Python3.6正式版新特性预览  如何快速选择适合个人网站的云服务器配置?  郑州企业网站制作公司,郑州招聘网站有哪些?  Laravel的路由模型绑定怎么用_Laravel Route Model Binding简化控制器逻辑  Laravel如何升级到最新的版本_Laravel版本升级流程与兼容性处理  百度浏览器网页无法复制文字怎么办 百度浏览器复制修复  ,交易猫的商品怎么发布到网站上去?  如何安全更换建站之星模板并保留数据?  Linux虚拟化技术教程_KVMQEMU虚拟机安装与调优  Edge浏览器提示“由你的组织管理”怎么解决_去除浏览器托管提示【修复】  昵图网官网入口 昵图网素材平台官方入口  阿里云网站搭建费用解析:服务器价格与建站成本优化指南  网站制作价目表怎么做,珍爱网婚介费用多少?  Laravel如何使用Passport实现OAuth2?(完整配置步骤)  Laravel如何实现全文搜索功能?(Scout和Algolia示例)  制作无缝贴图网站有哪些,3dmax无缝贴图怎么调?  Laravel怎么进行浏览器测试_Laravel Dusk自动化浏览器测试入门  高端建站如何打造兼具美学与转化的品牌官网?  Laravel如何构建RESTful API_Laravel标准化API接口开发指南  laravel怎么用DB facade执行原生SQL查询_laravel DB facade原生SQL执行方法  Laravel如何配置.env文件管理环境变量_Laravel环境变量使用与安全管理  如何自定义建站之星模板颜色并下载新样式?  中山网站推广排名,中山信息港登录入口?  HTML5空格和margin有啥区别_空格与外边距的使用场景【说明】  Laravel表单请求验证类怎么用_Laravel Form Request分离验证逻辑教程  HTML5空格在Angular项目里怎么处理_Angular中空格的渲染问题【详解】  深圳网站制作的公司有哪些,dido官方网站?  Laravel怎么为数据库表字段添加索引以优化查询  中山网站制作网页,中山新生登记系统登记流程?