Saturday, January 18, 2025

[Golang] Phần 22 – Go Date & Time

-

1. Tổng quan.

Trong ngôn ngữ lập trình Go (Golang), package time cung cấp các hàm và loại dữ liệu để thao tác với thời gian và đồng hồ. Package này hỗ trợ các chức năng như đo thời gian, định dạng thời gian, và thực hiện các phép toán liên quan đến thời gian.

Dưới đây là một số khái niệm quan trọng trong package time:

  • Thời Gian (Time):
    • time.Time là một kiểu dữ liệu trong package time đại diện cho một điểm cụ thể trong thời gian.
  • Định Dạng Thời Gian (Time Formatting):
    • Hàm time.Format cho phép bạn định dạng một thời gian thành một chuỗi theo các chuẩn định sẵn hoặc theo mẫu tùy chỉnh.
  • Thao Tác Thời Gian (Time Manipulation):
    • Các hàm như time.Add, time.Sub giúp thực hiện các phép toán thao tác thời gian như cộng/trừ thời gian.
  • Timer và Tickers:
    • time.Timertime.Ticker là các cấu trúc dữ liệu hỗ trợ thực hiện các hành động sau một khoảng thời gian nhất định.
  • Sleep:
    • Hàm time.Sleep cho phép bạn tạm dừng thực thi của Goroutine trong một khoảng thời gian xác định.

Ví dụ 1 – Dưới đây là một ví dụ cơ bản sử dụng package time.

package main

import (
	"fmt"
	"time"
)

func main() {
	// Lấy thời gian hiện tại
	now := time.Now()
	fmt.Println("Current time:", now)

	// Định dạng thời gian
	formattedTime := now.Format("2006-01-02 15:04:05")
	fmt.Println("Formatted time:", formattedTime)

	// Tạm dừng thực thi trong 2 giây
	fmt.Println("Sleeping for 2 seconds...")
	time.Sleep(2 * time.Second)
	fmt.Println("Awake!")

	// Sử dụng Timer để thực hiện một hành động sau 3 giây
	timer := time.NewTimer(3 * time.Second)
	<-timer.C
	fmt.Println("Timer expired!")
}

Trong ví dụ trên, chúng ta sử dụng time.Now để lấy thời gian hiện tại, time.Format để định dạng thời gian, time.Sleep để tạm dừng thực thi, và time.Timer để thực hiện một hành động sau một khoảng thời gian nhất định.

Ví dụ 2 – Time package time hỗ trợ định dạng timestamp.

Package time trong Go cung cấp các hàm để chuyển đổi giữa các đối tượng thời gian và timestamp (Unix time). Cụ thể, các phương thức Unix()UnixNano() của kiểu dữ liệu time.Time có thể được sử dụng để chuyển đổi một time.Time thành timestamp (giây hoặc nano giây kể từ thời điểm Unix epoch).

Dưới đây là một ví dụ:

package main

import (
	"fmt"
	"time"
)

func main() {
	// Tạo một thời điểm
	currentTime := time.Now()
	fmt.Println("Current time:", currentTime)

	// Chuyển đổi thành timestamp (giây)
	timestampSeconds := currentTime.Unix()
	fmt.Println("Timestamp (seconds):", timestampSeconds)

	// Chuyển đổi thành timestamp (nano giây)
	timestampNanoSeconds := currentTime.UnixNano()
	fmt.Println("Timestamp (nanoseconds):", timestampNanoSeconds)

	// Chuyển đổi từ timestamp về thành thời gian
	timeFromTimestamp := time.Unix(timestampSeconds, 0)
	fmt.Println("Time from timestamp (seconds):", timeFromTimestamp)

	// Chuyển đổi từ timestamp (nano giây) về thành thời gian
	timeFromNanoTimestamp := time.Unix(0, timestampNanoSeconds)
	fmt.Println("Time from timestamp (nanoseconds):", timeFromNanoTimestamp)
}

Ví dụ 3 – Ví dụ tổng hợp.

Để đo thời gian hoàn thành cho mỗi IP và tổng thời gian hoàn thành cho tất cả các IP, bạn có thể sử dụng time package để ghi nhận thời gian bắt đầu và kết thúc của mỗi goroutine.

Dưới đây là một ví dụ chương trình thực hiện điều này (ví dụ này mình sử dụng tiếp ví dụ 3 của bài https://wiki.hoanghd.com/golang-phan-22-go-goroutine/ bạn hãy bấm vào link để ví dụ trước).

package main

import (
	"os/exec"
	"regexp"
	"fmt"
	"sync"
	"time"
)

func main() {
	// Danh sách các địa chỉ IP cần kiểm tra
	ipAddresses := []string{"8.8.8.1", "8.8.8.2", "8.8.8.3", "8.8.8.8", "8.8.8.5", "8.8.8.6", "8.8.8.7", "8.8.8.8", "8.8.8.9", "google.com", "wiki.hoanghd.com", "zing.vn"}

	// Sử dụng WaitGroup để đợi tất cả các goroutine hoàn thành
	var wg sync.WaitGroup

	// Sử dụng Mutex để bảo vệ biến totalTime
	var mu sync.Mutex
	var totalTime time.Duration

	// Vòng lặp qua từng địa chỉ IP trong danh sách
	for _, ipaddr := range ipAddresses {
		// Tăng đếm cho mỗi goroutine mới
		wg.Add(1)

		// Thời điểm bắt đầu của goroutine
		startTime := time.Now()

		// Goroutine để thực hiện kiểm tra cho mỗi IP
		go func(ip string, startTime time.Time) {
			defer wg.Done()

			// Thực hiện lệnh ping và lấy kết quả đầu ra
			var count string = "1"

			cmd := exec.Command("ping", "-c", count, ip)
			out, err := cmd.CombinedOutput()

			// Kiểm tra lỗi trước khi xử lý đầu ra
			if err != nil {
				fmt.Printf("Error while pinging %s: %s\n", ip, err)
				return
			}

			// Chuyển đổi đầu ra thành chuỗi
			output := string(out)

			// Sử dụng regex để tìm kiếm giá trị "0%" trong đoạn văn bản
			re := regexp.MustCompile(`(\d+)% packet loss`)
			matches := re.FindStringSubmatch(output)

			// Kiểm tra nếu có matches và lấy giá trị tương ứng
			if len(matches) > 1 {
				packetLoss := matches[1]
				fmt.Printf("Check IP: %s, Packet Loss: %s\n", ip, packetLoss)
			} else {
				fmt.Printf("Không tìm thấy thông tin về packet loss cho IP: %s\n", ip)
			}

			// Thời điểm kết thúc của goroutine
			endTime := time.Now()

			// Thời gian thực hiện cho goroutine này
			duration := endTime.Sub(startTime)

			// Bảo vệ biến totalTime với Mutex
			mu.Lock()
			totalTime += duration
			mu.Unlock()

			// In ra thời gian thực hiện cho mỗi IP
			fmt.Printf("Time taken for IP %s: %s\n", ip, duration)
		}(ipaddr, startTime)
	}

	// Đợi cho tất cả các goroutine hoàn thành trước khi kết thúc chương trình
	wg.Wait()

	// In ra tổng thời gian thực hiện cho tất cả các IP
	fmt.Printf("Total time taken for all IPs: %s\n", totalTime)
}

Trong ví dụ này, thời gian bắt đầu và kết thúc của mỗi goroutine được ghi lại, và tổng thời gian thực hiện cho tất cả các IP cũng được tính toán và in ra sau khi tất cả các goroutine hoàn thành. Sử dụng sync.Mutex để bảo vệ biến totalTime giúp đảm bảo tính nhất quán khi nhiều goroutine cùng truy cập.

$ go run main.go 
Check IP: 8.8.8.8, Packet Loss: 0
Time taken for IP 8.8.8.8: 44.592891ms
Check IP: 8.8.8.8, Packet Loss: 0
Time taken for IP 8.8.8.8: 51.2905ms
Check IP: zing.vn, Packet Loss: 0
Time taken for IP zing.vn: 84.396437ms
Check IP: google.com, Packet Loss: 0
Time taken for IP google.com: 137.708762ms
Check IP: wiki.hoanghd.com, Packet Loss: 0
Time taken for IP wiki.hoanghd.com: 143.859721ms
Error while pinging 8.8.8.1: exit status 1
Error while pinging 8.8.8.6: exit status 1
Error while pinging 8.8.8.7: exit status 1
Error while pinging 8.8.8.9: exit status 1
Error while pinging 8.8.8.5: exit status 1
Error while pinging 8.8.8.3: exit status 1
Error while pinging 8.8.8.2: exit status 1
Total time taken for all IPs: 461.848311ms

LEAVE A REPLY

Please enter your comment!
Please enter your name here

4,956FansLike
256FollowersFollow
223SubscribersSubscribe
spot_img

Related Stories