+8

Phần 2: Khám phá golang - Packages, biến và hàm

Packages

Giới thiệu

  • Packages(Gói) trong Go là một cách để tổ chức và tái sử dụng trong source code.
  • Packages cho phép phân chia source code thành các phần nhỏ hơn, giúp dễ dàng quản lý code trong dự án
  • Trong Golang, mỗi file đều thuộc một package. Tên của package là tên thư mục chứa file đó.

Sử dụng

  • Để sử dụng các chức năng từ một package khác, bạn cần import package đó vào file của mình. Cú pháp:
    import "tên_package" \

    Ví dụ: Import "fmt" để sử dụng các chức năng in và định dạng trong package fmt.

    Theo quy ước, tên gói giống với phần tử cuối cùng của đường dẫn nhập. Ví dụ: gói "math/rand" bao gồm các tệp bắt đầu bằng gói câu lệnh rand.

    package main
    
    
    import (
        "fmt"
        "math/rand"
    )
    func main() {
        fmt.Println("My lucky number is", rand.Intn(100))
    } 
    
  • Go cung cấp nhiều packages chuẩn giúp thực hiện các công việc phổ biến như định dạng in ra đọc ghi file, network,...

  • Ngoài việc sử dụng các packages chuẩn, bạn có thể tạo và sử dụng các packages do chính bạn định nghĩa bằng cách file của mình trong cùng một thư mục và đặt tên thư mục là tên của package.

  • Trong các dự án lớn, việc quản lý dependency giữa các packages là rất quan trọng. Go modules là một cách để quản lý dependency và phiên bản của các packages.

Exported names

  • Trong Go, một tên được export nếu nó bắt đầu bằng một chữ cái viết hoa. Ví dụ, "Hello" là một tên được export, cũng như "Pi", được export từ package "math".
  • "hello" và "pi" không bắt đầu bằng một chữ cái viết hoa, vì vậy chúng không được export.
  • Khi import một package, bạn chỉ có thể tham chiếu đến các tên được export của nó. Bất kỳ tên không được export(unexported) nào đều không thể truy cập từ bên ngoài package. Ví dụ:
// Trong file math.go
package math

// Pi là một biến được export
const Pi = 3.14159

// pizza là một biến không được export
var hello = "Xin chào"

// CalculateArea là một hàm được export
func CalculateArea(radius float64) float64 {
    return Pi * radius * radius
}

// calculateVolume là một hàm không được export
func calculateVolume(radius float64) float64 {
    return (4.0 / 3.0) * Pi * radius * radius * radius
}

Functions

  • Một function(hàm) có thể nhận không hoặc nhiều hơn một đối số.
// Hàm nhận 1 đối số
func greet(name string) {
    fmt.Println("Hello,", name)
}

// Hàm không nhận đối số
func main() {
    greet("Alice")
}
  • Functions continued: Khi hai hoặc nhiều tham số liên tiếp trong hàm có cùng một kiểu dữ liệu, bạn có thể bỏ qua kiểu dữ liệu ở tất cả trừ tham số cuối cùng.
// x int, y int có thể viêt ngắn thành x, y int
func add(a, b int) int {
    return a + b
}

func main() {
    sum := add(3, 5)
    fmt.Println("Sum:", sum)
}
  • Multiple results: Một hàm có thể trả về đồng thời nhiều kết quả
// Hàm divide trả về 2 giá trị
// 1: Kiểu float64: Kết quả a/b hoặc 0
// 2: error: một error hoặc nil
func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, errors.New("cannot divide by zero")
    }
    return a / b, nil
}

func main() {
    result, err := divide(10, 2)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Println("Result:", result)
}
  • Named return values: Giá trị trả về của hàm trong Go có thể được đặt tên, các tên này nên được sử để mô tả ý nghĩa của giá trị trả về. Một return mà không có đối số trả về sẽ trả về các giá trị được đặt tên, điều này được gọi là "naked" return. Thường nó sẽ được sử dụng trong các hàm ngắn.
func split(sum int) (x, y int) {
	x = sum * 2 / 10
	y = sum - x
	return
}

func main() {
	fmt.Println(split(30))   // kết quả: 6 24
}

Variables

Khai báo và khởi tạo

  • Khai báo variables(biến): Câu lệnh "var", có thể khai báo một hoặc nhiều biến
  • Kiểu dữ liệu của biến được đặt ở cuối cùng sau tên biến Ví dụ:
var age int
var name string
var isActive bool
  • Khởi tạo: Khởi tạo biến bằng cách gán giá trị cho biến sau dấu "=" Ví dụ:
var age int = 30
var name string = "Jim John"
var isActive bool = true
  • Khai báo biến ngắn gọn: câu lệnh gán ngắn := có thể được sử dụng thay cho khai báo var với kiểu ẩn. Ví dụ:
age := 30
name := "Jim John"
isActive := true

Lưu ý: Cách khai báo biến này chỉ có thể dùng ở trong 1 hàm.

Các loại biến cơ bản

I - Số

Các số được chia thành ba loại con như sau:
1. Số nguyên (Integer)
Cả số nguyên có dấu và không dấu đều có sẵn trong bốn kích thước khác nhau như được hiển thị trong bảng dưới đây. Số nguyên có dấu được biểu diễn bằng int và số nguyên không dấu được biểu diễn bằng uint.
Các phép toán số học có thể thực hiện: Cộng, trừ, nhân, chia, phần dư

Data type Description
int8 8-bit signed integer
int16 16-bit signed integer
int32 32-bit signed integer
int64 64-bit signed integer
uint8 8-bit unsigned integer
uint16 16-bit unsigned integer
uint32 32-bit unsigned integer
uint64 64-bit unsigned integer
int Both int and uint contain same size, either 32 or 64 bit.
uint Both int and uint contain same size, either 32 or 64 bit.
rune It is a synonym of int32 and also represent Unicode code points.
byte It is a synonym of uint8.
uintptr t is an unsigned integer type. Its width is not defined, but its can hold all the bits of a pointer value.


Ví dụ:

   // Using 8-bit unsigned int 
    var a uint8 = 225
    fmt.Println(a, a-3)
     
    // Using 16-bit signed int 
    var b int16 = 32767
    fmt.Println(b+2, b-2) 
    
    fmt.Println("Example of arithmetic operations:")
    var x int16 = 170
    var y int16 = 83
    //Addition
    fmt.Printf(" addition :  %d + %d = %d\n ", x, y, x+y)
    //Subtraction
    fmt.Printf("subtraction : %d - %d = %d\n", x, y, x-y)
    //Multiplication
    fmt.Printf(" multiplication : %d * %d = %d\n", x, y, x*y)
    //Division
    fmt.Printf(" division : %d / %d = %d\n", x, y, x/y)
    //Modulus
    fmt.Printf(" remainder : %d %% %d = %d\n", x, y, x%y)

Output:

225 222
-32767 32765
Example of arithmetic operations:
 addition :  170 + 83 = 253
 subtraction : 170 - 83 = 87
 multiplication : 170 * 83 = 14110
 division : 170 / 83 = 2
 remainder : 170 % 83 = 4

2. Số thực (Float)
Số thực được chia thành 2 loại như bảng dưới. Các phép toán số học có thể thực hiện: Cộng, trừ, nhân, chia.

Data type Description
float32 32-bit IEEE 754 floating-point number
float64 64-bit IEEE 754 floating-point number


Ví dụ:

    a := 20.45
    b := 34.89
     
    c := b-a
     
    // Display the result 
    fmt.Printf("Result is: %f", c)
     
    // Display the type of c variable
    fmt.Printf("\nThe type of c is : %T", c)  

Output:

Result is: 14.440000
The type of c is : float64

3. Số phức (Complex)
Số phức (Complex Numbers): Các số phức được chia thành hai phần như được hiển thị trong bảng dưới đây. float32 và float64 cũng là một phần của các số phức này. Hàm tích hợp sẵn tạo ra một số phức từ phần ảo và phần thực của nó và hàm ảo và thực tích hợp sẵn trích xuất các phần đó.

Data type Description
complex64 Complex numbers which contain float32 as a real and imaginary component.
complex128 Complex numbers which contain float64 as a real and imaginary component.


Ví dụ:

   var a complex128 = complex(6, 2)
   var b complex64 = complex(9, 2)
   fmt.Println(a)
   fmt.Println(b)
    
  // Display the type 
  fmt.Printf("The type of a is %T and "+
            "the type of b is %T", a, b)

Output:

(6+2i)
(9+2i)
The type of a is complex128 and the type of b is complex64

II - Booleans

Kiểu dữ liệu boolean đại diện cho chỉ một bit thông tin có thể là true hoặc false. Các giá trị của kiểu boolean không được chuyển đổi một cách ngầm định hoặc rõ ràng sang bất kỳ kiểu dữ liệu nào khác.
Ví dụ:

 // variables
   str1 := "GolangEssentials"
   str2:= "golangEssentials"
   str3:= "golangessentials"
   result1:= str1 == str2
   result2:= str1 == str3
    
   // Display the result
   fmt.Println( result1)
   fmt.Println( result2)
    
   // Display the type of 
   // result1 and result2
   fmt.Printf("The type of result1 is %T and "+ "the type of result2 is %T", result1, result2)

Output:

false
false
The type of result1 is bool and the type of result2 is bool

III - Strings

Kiểu dữ liệu chuỗi (string) đại diện cho một chuỗi các điểm mã Unicode. Hay nói cách khác, ta có thể nói rằng một chuỗi là một chuỗi các byte không thể thay đổi, có nghĩa là một khi một chuỗi đã được tạo ra thì bạn không thể thay đổi chuỗi đó. Một chuỗi có thể chứa dữ liệu tùy ý, bao gồm cả byte có giá trị không trong dạng có thể đọc được cho con người. Các chuỗi có thể được ghép lại bằng toán tử cộng (+).
Ví dụ:

 // str variable which stores strings
   str := "GolangEssentials"
    
   // Display the length of the string
   fmt.Printf("Length of the string is:%d",len(str))
    
   // Display the string
   fmt.Printf("\nString is: %s", str)
    
   // Display the type of str variable
   fmt.Printf("\nType of str is: %T", str)

Output:

Length of the string is:16
String is: GolangEssentials
Type of str is: string

Một số lưu ý

  • Default value: Các biến được khai báo mà không có giá trị khởi tạo rõ ràng sẽ được gán giá trị default: 0 đối với kiểu số, false đối với kiểu bolean và ""(the empty string) với chuỗi
    var i int
	var f float64
	var b bool
	var s string
	fmt.Printf("%v %v %v %q\n", i, f, b, s)

Output:

0 0 false ""
  • Ép kiểu: Trong Go, các kiểu dữ liệu có thể chuyển đổi bằng cách sử dụng toán tử type(value) \
    a := 5      //int
    b := 3.4    //float64
    
    sumFloat := float64(a) + b
    fmt.Println(sumFloat) // Output = 8.4
    
    sumInt := a + int(b)
    fmt.Println(sumInt) // Output = 8
  • Hằng số(constants): Hằng số được khai báo giống như biến, nhưng sử dụng từ khóa const. Hằng số có thể là ký tự, chuỗi, boolean, hoặc giá trị số. Không thể khai báo hằng số bằng cú pháp :=. package main

import "fmt"

const Pi = 3.14

func main() { const World = "Jim John" fmt.Println("Hello", World) fmt.Println("Happy", Pi, "Day")

const Truth = true
fmt.Println("Go rules?", Truth)

}

Kết bài

Trong bài thứ 2 này mình đã giới thiệu với các bạn những khái niệm cơ bản cũng như quan trọng nhất về package, hàm và biến. Còn rất nhiều loại biến thú vị nữa mà mình sẽ tiếp tục giới thiệu ở những bài viết sau 😄 Nếu có thắc mắc hoặc phát hiện bài viết có thiếu sót gì, hãy comment cho mình biết để mình kịp thời chỉnh sửa cũng như cùng thảo luận về thắc mắc đó nhé 😉 Hi vọng những kiến thức này sẽ giúp ích được các bạn trong hành trình chinh phục Golang. Hẹn gặp lại ở những bài viết tiếp theo trong series Golang Essentials: Nền Tảng và Kiến Thức Cơ Bản. See ya!

Tham khảo: https://www.geeksforgeeks.org/data-types-in-go/


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí