
Go语言网络编程深度解析网络编程是Go语言最擅长的领域之一。本文将深入探讨Go语言网络编程的核心概念和高级技巧。一、TCP编程基础1.1 TCP服务器package main import ( bufio fmt net strings ) func handleConnection(conn net.Conn) { defer conn.Close() reader : bufio.NewReader(conn) for { message, err : reader.ReadString(\n) if err ! nil { fmt.Println(Error reading:, err.Error()) return } fmt.Print(Received message:, string(message)) response : strings.ToUpper(message) conn.Write([]byte(response)) } } func main() { listener, err : net.Listen(tcp, :8080) if err ! nil { fmt.Println(Error listening:, err.Error()) return } defer listener.Close() fmt.Println(Server listening on port 8080) for { conn, err : listener.Accept() if err ! nil { fmt.Println(Error accepting:, err.Error()) return } go handleConnection(conn) } }1.2 TCP客户端package main import ( bufio fmt net os strings ) func main() { conn, err : net.Dial(tcp, localhost:8080) if err ! nil { fmt.Println(Error connecting:, err.Error()) return } defer conn.Close() reader : bufio.NewReader(os.Stdin) for { fmt.Print(Enter message: ) message, _ : reader.ReadString(\n) _, err : conn.Write([]byte(message)) if err ! nil { fmt.Println(Error sending:, err.Error()) return } buffer : make([]byte, 1024) n, err : conn.Read(buffer) if err ! nil { fmt.Println(Error reading:, err.Error()) return } fmt.Println(Response:, string(buffer[:n])) if strings.TrimSpace(message) exit { break } } }二、HTTP服务器开发2.1 基础HTTP服务器package main import ( fmt net/http ) func helloHandler(w http.ResponseWriter, r *http.Request) { if r.URL.Path ! /hello { http.Error(w, 404 not found, http.StatusNotFound) return } if r.Method ! GET { http.Error(w, Method not allowed, http.StatusMethodNotAllowed) return } fmt.Fprintf(w, Hello, World!) } func main() { http.HandleFunc(/hello, helloHandler) fmt.Println(Server starting on :8080) http.ListenAndServe(:8080, nil) }2.2 路由与中间件type Router struct { routes map[string]map[string]http.HandlerFunc middlewares []func(http.HandlerFunc) http.HandlerFunc } func NewRouter() *Router { return Router{ routes: make(map[string]map[string]http.HandlerFunc), } } func (r *Router) Use(mw func(http.HandlerFunc) http.HandlerFunc) { r.middlewares append(r.middlewares, mw) } func (r *Router) Handle(method, path string, handler http.HandlerFunc) { if _, ok : r.routes[method]; !ok { r.routes[method] make(map[string]http.HandlerFunc) } r.routes[method][path] handler } func (r *Router) Get(path string, handler http.HandlerFunc) { r.Handle(GET, path, handler) } func (r *Router) Post(path string, handler http.HandlerFunc) { r.Handle(POST, path, handler) } func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) { method : req.Method path : req.URL.Path handlers, ok : r.routes[method] if !ok { http.Error(w, Method not allowed, http.StatusMethodNotAllowed) return } handler, ok : handlers[path] if !ok { http.Error(w, Not found, http.StatusNotFound) return } for _, mw : range r.middlewares { handler mw(handler) } handler(w, req) } func loggingMiddleware(next http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { fmt.Printf(%s %s\n, r.Method, r.URL.Path) next(w, r) } }2.3 HTTP客户端package main import ( fmt io/ioutil net/http time ) func main() { client : http.Client{ Timeout: 10 * time.Second, Transport: http.Transport{ MaxIdleConns: 100, IdleConnTimeout: 30 * time.Second, TLSHandshakeTimeout: 5 * time.Second, }, } req, err : http.NewRequest(GET, https://api.example.com/data, nil) if err ! nil { fmt.Println(Error creating request:, err) return } req.Header.Set(Authorization, Bearer token) req.Header.Set(Content-Type, application/json) resp, err : client.Do(req) if err ! nil { fmt.Println(Error making request:, err) return } defer resp.Body.Close() body, err : ioutil.ReadAll(resp.Body) if err ! nil { fmt.Println(Error reading response:, err) return } fmt.Println(string(body)) }三、WebSocket编程3.1 WebSocket服务器package main import ( fmt net/http github.com/gorilla/websocket ) var upgrader websocket.Upgrader{ ReadBufferSize: 1024, WriteBufferSize: 1024, CheckOrigin: func(r *http.Request) bool { return true }, } func wsHandler(w http.ResponseWriter, r *http.Request) { conn, err : upgrader.Upgrade(w, r, nil) if err ! nil { fmt.Println(Error upgrading:, err) return } defer conn.Close() for { messageType, p, err : conn.ReadMessage() if err ! nil { fmt.Println(Error reading:, err) return } fmt.Printf(Received: %s\n, p) err conn.WriteMessage(messageType, p) if err ! nil { fmt.Println(Error writing:, err) return } } } func main() { http.HandleFunc(/ws, wsHandler) http.ListenAndServe(:8080, nil) }3.2 WebSocket客户端package main import ( fmt log os github.com/gorilla/websocket ) func main() { conn, _, err : websocket.DefaultDialer.Dial(ws://localhost:8080/ws, nil) if err ! nil { log.Fatal(Dial error:, err) } defer conn.Close() done : make(chan struct{}) go func() { defer close(done) for { _, message, err : conn.ReadMessage() if err ! nil { log.Println(Read error:, err) return } fmt.Printf(Received: %s\n, message) } }() for { var input string fmt.Scanln(input) err : conn.WriteMessage(websocket.TextMessage, []byte(input)) if err ! nil { log.Println(Write error:, err) return } if input exit { break } } }四、gRPC编程4.1 定义.proto文件syntax proto3; package user; option go_package ./userpb; service UserService { rpc GetUser(GetUserRequest) returns (GetUserResponse); rpc ListUsers(ListUsersRequest) returns (ListUsersResponse); rpc CreateUser(CreateUserRequest) returns (CreateUserResponse); rpc UpdateUser(UpdateUserRequest) returns (UpdateUserResponse); rpc DeleteUser(DeleteUserRequest) returns (DeleteUserResponse); } message User { string id 1; string name 2; string email 3; int32 age 4; } message GetUserRequest { string id 1; } message GetUserResponse { User user 1; } message ListUsersRequest {} message ListUsersResponse { repeated User users 1; } message CreateUserRequest { string name 1; string email 2; int32 age 3; } message CreateUserResponse { User user 1; } message UpdateUserRequest { string id 1; string name 2; string email 3; int32 age 4; } message UpdateUserResponse { User user 1; } message DeleteUserRequest { string id 1; } message DeleteUserResponse { bool success 1; }4.2 gRPC服务器实现package main import ( context fmt net google.golang.org/grpc pb your/package/path/userpb ) type server struct { pb.UnimplementedUserServiceServer users map[string]*pb.User } func (s *server) GetUser(ctx context.Context, req *pb.GetUserRequest) (*pb.GetUserResponse, error) { user, ok : s.users[req.Id] if !ok { return nil, fmt.Errorf(user not found) } return pb.GetUserResponse{User: user}, nil } func (s *server) ListUsers(ctx context.Context, req *pb.ListUsersRequest) (*pb.ListUsersResponse, error) { users : make([]*pb.User, 0, len(s.users)) for _, user : range s.users { users append(users, user) } return pb.ListUsersResponse{Users: users}, nil } func (s *server) CreateUser(ctx context.Context, req *pb.CreateUserRequest) (*pb.CreateUserResponse, error) { user : pb.User{ Id: fmt.Sprintf(user-%d, len(s.users)1), Name: req.Name, Email: req.Email, Age: req.Age, } s.users[user.Id] user return pb.CreateUserResponse{User: user}, nil } func main() { lis, err : net.Listen(tcp, :50051) if err ! nil { fmt.Println(Error listening:, err) return } s : grpc.NewServer() pb.RegisterUserServiceServer(s, server{ users: make(map[string]*pb.User), }) fmt.Println(gRPC server listening on :50051) s.Serve(lis) }4.3 gRPC客户端实现package main import ( context fmt google.golang.org/grpc pb your/package/path/userpb ) func main() { conn, err : grpc.Dial(localhost:50051, grpc.WithInsecure()) if err ! nil { fmt.Println(Error connecting:, err) return } defer conn.Close() client : pb.NewUserServiceClient(conn) createResp, err : client.CreateUser(context.Background(), pb.CreateUserRequest{ Name: 张三, Email: zhangsanexample.com, Age: 25, }) if err ! nil { fmt.Println(Error creating user:, err) return } fmt.Println(Created user:, createResp.User.Id) getResp, err : client.GetUser(context.Background(), pb.GetUserRequest{ Id: createResp.User.Id, }) if err ! nil { fmt.Println(Error getting user:, err) return } fmt.Println(Got user:, getResp.User.Name) }五、网络编程最佳实践5.1 连接池管理type ConnectionPool struct { mu sync.Mutex connections []*net.Conn maxSize int address string } func NewConnectionPool(address string, maxSize int) *ConnectionPool { return ConnectionPool{ connections: make([]*net.Conn, 0, maxSize), maxSize: maxSize, address: address, } } func (p *ConnectionPool) Get() (*net.Conn, error) { p.mu.Lock() defer p.mu.Unlock() if len(p.connections) 0 { conn : p.connections[len(p.connections)-1] p.connections p.connections[:len(p.connections)-1] return conn, nil } if len(p.connections) p.maxSize { return nil, fmt.Errorf(pool is full) } conn, err : net.Dial(tcp, p.address) if err ! nil { return nil, err } return conn, nil } func (p *ConnectionPool) Put(conn *net.Conn) { p.mu.Lock() defer p.mu.Unlock() if len(p.connections) p.maxSize { p.connections append(p.connections, conn) } else { (*conn).Close() } }5.2 超时控制func fetchWithTimeout(url string, timeout time.Duration) (string, error) { ctx, cancel : context.WithTimeout(context.Background(), timeout) defer cancel() req, err : http.NewRequestWithContext(ctx, GET, url, nil) if err ! nil { return , err } resp, err : http.DefaultClient.Do(req) if err ! nil { return , err } defer resp.Body.Close() return ioutil.ReadAll(resp.Body) }5.3 错误处理func handleError(err error, context string) bool { if err nil { return false } switch { case errors.Is(err, context.DeadlineExceeded): log.Printf(%s: request timed out, context) case errors.Is(err, io.EOF): log.Printf(%s: connection closed, context) default: log.Printf(%s: %v, context, err) } return true }六、总结Go语言的网络编程能力非常强大TCP编程基础的socket编程支持高并发HTTP服务器内置net/http包支持路由和中间件WebSocket实时双向通信适合实时应用gRPC高性能RPC框架适合微服务通信最佳实践连接池、超时控制、错误处理掌握这些知识可以构建高效、可靠的网络应用。