Giá trị và tham chiếu
Bài học 7 trên 19 trong khóa học Hàm và con trỏ trong Go của Coddy.
Đến đây, chúng ta đã học cách sử dụng tham số và giá trị trả về từ các hàm. Trong bài học này, chúng ta sẽ giải thích một khái niệm quan trọng khác mà bạn cần hiểu khi làm việc với hàm.
Hãy xem xét một chương trình như sau:
func main() {
a := 5
fmt.Println("value of a:", a)
sum(a)
fmt.Println("value of a after addition:", a)
}
func sum(x int) {
x = x + x
}Trong chương trình này, chúng ta khai báo biến a, in ra giá trị của nó, rồi truyền nó vào một hàm có tên sum. Hàm này thực hiện phép cộng 5 + 5. Bạn nghĩ đoạn code này sẽ cho kết quả gì?
Hãy chạy thử để xem:
value of a: 5
value of a after addition: 5Không có gì thay đổi. Ở đây có vấn đề: a lẽ ra phải bằng 10 sau khi gọi hàm sum, đúng không?
Thật ra là không, vì trong Go, khi truyền một giá trị vào hàm, chúng ta chỉ sao chép giá trị đó. Khi thay đổi giá trị, thay đổi ấy không xuất hiện bên ngoài hàm. Giá trị chỉ thay đổi bên trong hàm. Bạn có thể thấy điều này nếu in ra giá trị bên trong hàm sum:
func main() {
a := 5
fmt.Println("value of a:", a)
sum(a)
fmt.Println("value of a after addition:", a)
}
func sum(x int) {
x = x + x
fmt.Println("value inside the function:", x)
}Nếu chạy chương trình này, chúng ta sẽ nhận được:
value of a: 5
value inside the function: 10
value of a after addition: 5Điều này có nghĩa là giá trị thay đổi bên trong hàm, tức là trong phạm vi của hàm (function scope), nhưng bên ngoài hàm thì giá trị không thay đổi.
Mình biết bạn cần thêm chi tiết để hiểu rõ điều này. Hãy xem sơ đồ sau:
Giờ thì bạn đã hiểu rồi. Cách này tạo ra một biến mới có địa chỉ khác, điều này cũng không tốt cho bộ nhớ !
Đó là lý do chúng ta không thấy các thay đổi, vì các biến khác nhau😅.
Để giải quyết vấn đề này, chúng ta có thể dùng con trỏ thay vì bản sao của giá trị, như sau:
func main() {
a := 5
fmt.Println("value of a:", a)
sum(&a)
fmt.Println("value of a after addition:", a)
}
func sum(x *int) {
*x += *x
}Bây giờ, thay vì truyền giá trị, chúng ta truyền địa chỉ bộ nhớ sum(&a). Điều này có nghĩa là hàm sẽ làm việc với chính biến đó và không tạo biến mới.
Thử thách
DễTrong đoạn code đã cho, chúng ta định nghĩa một hàm (function) để hoán đổi hai giá trị. Hãy hoàn thiện đoạn code để hàm hoạt động và đạt được kết quả.
Tự làm thử
package main
import "fmt"
func swapValues(a, b int) {
a, b = b, a
}
func main() {
var x, y int = 4,10
fmt.Println("Before swap:")
fmt.Println("x =", x)
fmt.Println("y =", y)
swapValues(x, y)
fmt.Println("After swap:")
fmt.Println("x =", x)
fmt.Println("y =", y)
}
Tất cả bài học trong Hàm và con trỏ trong Go
1Giới thiệu
Giới thiệu4Ôn tập các hàm xử lý chuỗi trong Go
Chuỗi trong GolangHàm nốiHàm kiểm tra chuỗi conHàm tìm chỉ sốThử thách ôn tập #1Tự luyện tập: Trình biên dịch Go online