Go語言函數參數傳遞:為什么指針變量在函數內修改后外部卻不變?

Go語言函數參數傳遞:為什么指針變量在函數內修改后外部卻不變?

go語言函數參數傳遞中的指針變量陷阱:為何函數內修改外部變量無效?

本文分析一個Go語言程序中關于指針變量賦值的常見問題。程序嘗試在函數內部修改指向數據庫連接對象的指針變量,但主函數中該變量卻未被修改。

以下代碼片段展示了這個問題:

var db *sql.DB  func main() {     initDB(db)     fmt.Println(db) // 打印 <nil> }  func initDB(db *sql.DB) {     var err error     db, err = sql.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/data")     checkErr(err)     db.SetMaxOpenConns(100)     db.SetMaxIdleConns(100)     db.SetConnMaxLifetime(time.Minute * 3)     if err := db.Ping(); err != nil {         checkErr(err)     }     fmt.Println(db) // 這里打印的是正確的值 }  func checkErr(err error) {     if err != nil {         panic(err)     } }

main 函數打印的 db 仍然是 nil,而 initDB 函數內部已成功連接數據庫。這是因為 Go 語言的函數參數傳遞機制是值傳遞。即使參數是指針類型,傳遞的也是指針值的副本。

立即學習go語言免費學習筆記(深入)”;

在 initDB 函數中,db, err := sql.Open(…) 創建了一個新的 *sql.DB 對象,并將該對象賦值給 initDB 函數內部的局部變量 db。這并沒有修改 main 函數中 db 變量的指向。initDB 函數結束后,其局部變量 db 被銷毀,main 函數中的 db 仍然是 nil。

要正確修改 main 函數中的 db 變量,需要使用指針的指針,或者在 initDB 函數中使用指針接收器。 以下是如何使用指針的指針來解決這個問題:

var db *sql.DB  func main() {     initDB(&db)     fmt.Println(db) // 現在將打印正確的值 }  func initDB(db **sql.DB) {     var err error     *db, err = sql.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/data")     checkErr(err)     (*db).SetMaxOpenConns(100)     (*db).SetMaxIdleConns(100)     (*db).SetConnMaxLifetime(time.Minute * 3)     if err := (*db).Ping(); err != nil {         checkErr(err)     }     fmt.Println(*db) // 這里打印的是正確的值 }  func checkErr(err error) {     if err != nil {         panic(err)     } }

通過傳遞 db 的地址 (&db),initDB 函數可以直接修改 main 函數中 db 變量的指向。

以上就是Go語言函數參數傳遞:

? 版權聲明
THE END
喜歡就支持一下吧
點贊9 分享