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 packagetime
đạ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.
- Hàm
- 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.
- Các hàm như
- Timer và Tickers:
time.Timer
vàtime.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.
- Hàm
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()
và 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