TCP 用戶端#
import "net"
func main() {
// 建立連線
conn, err := net.Dial("tcp", "example.com:80")
if err != nil {
log.Fatal(err)
}
defer conn.Close()
// 傳送請求
fmt.Fprintf(conn, "GET / HTTP/1.0\r\nHost: example.com\r\n\r\n")
// 讀取回應
response, _ := io.ReadAll(conn)
fmt.Println(string(response))
}TCP 伺服器#
func main() {
// 監聽埠口
listener, err := net.Listen("tcp", ":8080")
if err != nil {
log.Fatal(err)
}
defer listener.Close()
fmt.Println("伺服器啟動於 :8080")
for {
// 接受連線
conn, err := listener.Accept()
if err != nil {
log.Println("Accept error:", err)
continue
}
// 處理連線(併發)
go handleConnection(conn)
}
}
func handleConnection(conn net.Conn) {
defer conn.Close()
reader := bufio.NewReader(conn)
for {
message, err := reader.ReadString('\n')
if err != nil {
return
}
fmt.Printf("收到: %s", message)
conn.Write([]byte("收到訊息\n"))
}
}設定逾時#
// 連線逾時
conn, err := net.DialTimeout("tcp", "example.com:80", 5*time.Second)
// 讀寫逾時
conn.SetDeadline(time.Now().Add(10 * time.Second)) // 同時設定
conn.SetReadDeadline(time.Now().Add(5 * time.Second)) // 讀取逾時
conn.SetWriteDeadline(time.Now().Add(5 * time.Second)) // 寫入逾時在生產環境中,務必設定逾時。沒有逾時的網路操作可能導致 goroutine 永久阻塞。
UDP 通訊#
// UDP 用戶端
conn, _ := net.Dial("udp", "example.com:53")
defer conn.Close()
conn.Write([]byte("hello"))
// UDP 伺服器
addr := net.UDPAddr{Port: 8080}
conn, _ := net.ListenUDP("udp", &addr)
defer conn.Close()
buf := make([]byte, 1024)
n, remoteAddr, _ := conn.ReadFromUDP(buf)
fmt.Printf("收到來自 %s: %s\n", remoteAddr, buf[:n])HTTP 伺服器範例
import "net/http"
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:])
})
http.HandleFunc("/api/data", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]string{
"status": "ok",
})
})
log.Fatal(http.ListenAndServe(":8080", nil))
}Context 與網路操作#
import "context"
func fetchData(ctx context.Context, url string) ([]byte, error) {
req, _ := http.NewRequestWithContext(ctx, "GET", url, nil)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
return io.ReadAll(resp.Body)
}
func main() {
// 建立帶逾時的 context
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
data, err := fetchData(ctx, "https://example.com/api")
if err != nil {
if ctx.Err() == context.DeadlineExceeded {
log.Println("請求逾時")
}
return
}
fmt.Println(string(data))
}網路操作中使用
context.Context是最佳實務:
- 可以設定逾時與取消
- 可以傳遞請求範圍的值
- 可以優雅地終止整個請求鏈