Go – Mảng

Ngôn ngữ Go cung cấp một cấu trúc dữ liệu được gọi là mảng, có thể lưu trữ một tập hợp các phần tử tuần tự có kích thước cố định cùng kiểu với nhau. Một mảng thường được sử dụng để lưu trữ tập hợp dữ liệu, nhưng chúng ta có thể nghĩ theo hướng hữu ích hơn, một mảng giống như là một tập hợp các biến cùng kiểu.

Thay vì khai báo các biến cụ thể như là number0, number1, …, và number99, bạn khai báo một mảng numbers và sử dụng numbers[0], numbers[1], …, numbers[99] để tượng trưng cho các biến cụ thể. Phần tử cụ thể trong mảng được xác định bằng các index.

Tất cả các mảng bao gồm các vị trí bộ nhớ liên tiếp. Địa chỉ thấp nhất tương ứng với phần tử đầu tiên của mảng, và địa chỉ cao nhất là phần tử cuối cùng.

Khai báo mảng

Để khai báo một mảng trong Go, lập trình viên cần chỉ định kiểu của các phần tử, và số các phần tử được yêu cầu trong mảng

var tên_biến [Kích_thước] kiểu_biến

Ví dụ chúng ta có thể khai báo một mảng gồm 10 phần tử số nguyên

var a[10]int

Hãy cùng xem ví dụ sau đây

package main
import "fmt"

func main() {
	var x [5]int // Mảng 5 phần tử số nguyên
	fmt.Println(x)

	var y [8]string // mảng 8 phần tử string
	fmt.Println(y)

	var z [3]complex128 // mảng 3 phần tử complex
	fmt.Println(z)
}

Kết quả

[0 0 0 0 0]
[       ]
[(0+0i) (0+0i) (0+0i)]

Mặc định tất cả các phần tử của mảng được khởi tạo bằng 0, tùy theo kiểu dữ liệu của mảng.

Ví dụ nếu chúng ta khởi tạo một mảng số nguyên thì tất cả các phần tử đều được khởi tạo bằng 0. Nếu chúng ta khai báo một mảng string thì tất cả các phần tử được khởi tạo là string rỗng ""

Truy cập phần tử trong mảng bằng index

Các phần tử của mảng được lưu trữ tuần tự và có thể được truy cập bằng index. index bắt đầu bằng 0 và kết thúc bằng độ dài mảng – 1.

package main
import "fmt"

func main() {
	var x [5]int // Mảng gồm 5 phần tử số nguyên

	x[0] = 100
	x[1] = 101
	x[3] = 103
	x[4] = 105

	fmt.Printf("x[0] = %d, x[1] = %d, x[2] = %d\n", x[0], x[1], x[2])
	fmt.Println("x = ", x)
}

Kết quả

x[0] = 100, x[1] = 101, x[2] = 0
x =  [100 101 0 103 105]

Trong ví dụ ở trên, vì chúng ta không gán giá trị cho phần tử x[2], nên nó có giá trị bằng 0.

Khởi tạo mảng sử dụng literal

Bạn có thể khai báo một mảng như sau

var a = [5]int{2, 4, 6, 8, 10}

Cách khai báo mảng như trên được gọi là array literal

Chú ý rằng bạn không cần chỉ định cho kiểu của biến như là var a [5] int, bởi vì trình biên dịch sẽ tự suy luận ra dựa theo biểu thức bên phải.

Bạn cũng có thể sử dụng cách khai báo biến ngắn gọn của Go và khởi tạo một mảng như sau

a := [5]int{2, 4, 6, 8, 10}

Hãy xem ví dụ đầy đủ sau đây

package main
import "fmt"

func main() {
	// Khai báo và khởi tạo mảng cùng một lúc.
	var a = [5]int{2, 4, 6, 8, 10}
	fmt.Println(a)

	// Khai báo ngắn gọn và khởi tạo mảng.
	b := [5]int{2, 4, 6, 8, 10}
	fmt.Println(b)

	// Bạn không cần khởi tạo toàn bộ phần tử của mảng
	// Các phẩn tử không được khởi tạo sẽ được gán bằng 0 dựa theo kiểu của mảng
	c := [5]int{2}
	fmt.Println(c)
}

Cho phép trình biên dịch suy luận kích thước mảng

Bạn cũng có thể bỏ qua việc khai báo kích thước mảng từ biểu thức khởi tạo mảng, và để trình biên dịch đếm số phần tử của mảng

package main
import "fmt"

func main() {
	// để trình biên dịch suy luận ra kích thước của mảng
	a := [...]int{3, 5, 7, 9, 11, 13, 17}
	fmt.Println(a)
}

Kết quả

[3 5 7 9 11 13 17]

Độ dài mảng là một phần của kiểu

Độ dài của một mảng là một phần của kiểu. Nên mảng a[5]inta[10]intlà 2 kiểu hoàn toàn khác biệt, do đó bạn không thể gán hai mảng cho nhau.

Điều này nghĩa là bạn không thể thay đổi kích thước của một mảng, bởi vì khi bạn thay đổi kích thước của một mảng nghĩa là thay đổi kiểu của nó, và bạn không thể thay đổi kiểu của một biến trong Go

package main

func main() {
    var a = [5]int{3, 5, 7, 9, 11}
    var b [10]int = a  // Lỗi, a và b là 2 kiểu khác biệt
}

Mảng trong Go là kiểu giá trị

Mảng trong Go là kiểu giá trị, không giống như các ngôn ngữ khác như là C, C++, và Java mảng là kiểu tham chiếu.

Điều này nghĩa là khi bạn gán mảng cho một biến mới hoặc truyền một mảng cho một hàm, toàn bộ mảng được sao chép. Nên nếu bạn thay đổi bất cứ thông tin gì trong mảng được sao chép này, thì mảng gốc ban đầu sẽ không bị ảnh hưởng và không bị thay đổi.

package main
import "fmt"

func main() {
    a1 := [5]string{"English", "Japanese", "Spanish", "French", "Hindi"}
    a2 := a1 // sao chép mảng `a1` và gán cho `a2`

    a2[1] = "German"

    fmt.Println("a1 = ", a1) //  mảng `a1` không thay đổi.
    fmt.Println("a2 = ", a2)
}

Kết quả

a1 =  [English Japanese Spanish French Hindi]
a2 =  [English German Spanish French Hindi]

Lặp trên một mảng

Bạn có thể sử dụng vòng lặp for để lặp trên một mảng trong Go.

package main
import "fmt"

func main() {
	names := [3]string{"Mark Zuckerberg", "Bill Gates", "Larry Page"}

	for i := 0; i < len(names); i++ {
		fmt.Println(names[i])
	}
}

Kết quả

Mark Zuckerberg
Bill Gates
Larry Page

Hàm len() được sử dụng để tìm độ dài của mảng.

Hãy cùng xem ví dụ sau đây, tính tổng tất cả phần tử trong mảng bằng cách lặp từng phần tử trong mảng và cộng các phần tử với nhau vào biến sum

package main
import "fmt"

func main() {
	a := [4]float64{3.5, 7.2, 4.8, 9.5}
	sum := float64(0)

	for i := 0; i < len(a); i++ {
		sum = sum + a[i]
	}

	fmt.Printf("Sum of all the elements in array  %v = %f\n", a, sum)
}

Kết quả

Sum of all the elements in array  [3.5 7.2 4.8 9.5] = 25.000000

Lặp trên mảng sử dụng range

Go cung cấp một hình thức mạng mẽ hơn cho vòng lặp for sử dụng toán tử range.  Sau đây là cách bạn sử dụng toán tử range với vòng lặp for để lặp các phần tử trong mảng.

package main

import "fmt"

func main() {
	daysOfWeek := [7]string{"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}

	for index, value := range daysOfWeek {
		fmt.Printf("Day %d of week = %s\n", index, value)
	}
}

Kết quả

Day 0 of week = Mon
Day 1 of week = Tue
Day 2 of week = Wed
Day 3 of week = Thu
Day 4 of week = Fri
Day 5 of week = Sat
Day 6 of week = Sun

Hãy cùng viết lại phần ví dụ bên trên, tính tổng các phần tử trong mảng sử dụng toán tử range

package main
import "fmt"

func main() {
	a := [4]float64{3.5, 7.2, 4.8, 9.5}
	sum := float64(0)

	for index, value := range a {
		sum = sum + value
	}

	fmt.Printf("Sum of all the elements in array %v = %f", a, sum)
}

Kết quả

./array_iteration_range.go:9:13: index declared and not used

Trình biên dịch Go sẽ không cho phép tạo một biến mà không bao giờ sử dụng, bạn có thể sử dụng dấu _ thay cho index để trình biên dịch biết rằng đây là biến không sử dụng

package main
import "fmt"

func main() {
	a := [4]float64{3.5, 7.2, 4.8, 9.5}
	sum := float64(0)

	for _, value := range a {
		sum = sum + value
	}

	fmt.Printf("Sum of all the elements in array %v = %f", a, sum)
}

Kết quả

Sum of all the elements in array [3.5 7.2 4.8 9.5] = 25.000000

Mảng đa chiều trong Go

Tất cả các mảng mà chúng ta đã tạo cho đến giờ trong bài viết này đều là mảng một chiều. Bạn cũng có thể tạo mảng đa chiều trong Go.

Hãy cùng xem ví dụ sau đây

package main

import "fmt"

func main() {
	a := [2][2]int{
		{3, 5},
		{7, 9},	// Dấu phẩy này là bắt buộc
	}
	fmt.Println(a)

	// Giống như mảng một chiều, bạn không cần phải khởi tạo tất cả các phần tử trong mảng đa chiều
	// Các phần tử không được khởi tạo sẽ được gán bằng 0 dựa theo kiểu dữ liệu
	b := [3][4]float64{
		{1, 3},
		{4.5, -3, 7.4, 2},
		{6, 2, 11},
	}
	fmt.Println(b)
}

Kết quả

[[3 5] [7 9]]
[[1 3 0 0] [4.5 -3 7.4 2] [6 2 11 0]]

 

You May Also Like

About the Author: Nguyen Dinh Thuc

Leave a Reply

Your email address will not be published.