微服务的终极 Golang 框架:GoFr

news/2024/12/18 20:07:14/文章来源:https://www.cnblogs.com/cheyunhua/p/18615766

微服务的终极 Golang 框架:GoFr

原创 南丞 PFinalClub
 
PFinalClub
一个有信念者所开发出的力量,大于99个只有兴趣者。
113篇原创内容

微服务的终极 Golang 框架:GoFr

前言

Go 语言因其出色的并发处理能力和简洁的语法,成为开发微服务的理想选择。而 GoFr 框架则是一个专门为构建 Go 微服务而设计的框架,它提供了一套完整的工具和最佳实践,帮助开发者快速构建可靠的微服务应用。

GoFr 框架简介

GoFr 是一个专注于简单性和性能的微服务框架。它的主要特点包括:

  1. 零依赖:框架本身不依赖于任何第三方包
  2. 高性能:经过优化的路由和中间件系统
  3. 内置支持:包含了数据库、缓存、日志等常用功能
  4. 易于测试:提供了完整的测试工具和方法

快速开始

让我们通过一个简单的示例来了解 GoFr 的基本使用:

package main

import (
 "github.com/gofr-dev/gofr"
)

func main() {
 // 创建 GoFr 应用实例
 app := gofr.New()

 // 注册路由
 app.GET("/hello"func(ctx *gofr.Context) interface{} {
  return map[string]string{"message": "Hello, GoFr!"}
 })

 // 启动服务器
 app.Start()
}

核心功能详解

1. 路由系统

GoFr 提供了一个简单但强大的路由系统,支持各种 HTTP 方法和参数处理:

func setupRoutes(app *gofr.App) {
 // 基本路由
 app.GET("/users", getAllUsers)
 app.POST("/users", createUser)
 
 // 带参数的路由
 app.GET("/users/:id", getUserByID)
 
 // 路由组
 api := app.Group("/api/v1")
 api.GET("/products", getProducts)
 api.POST("/products", addProduct)
}

func getUserByID(ctx *gofr.Context) interface{} {
 id := ctx.PathParam("id")
 // 处理业务逻辑
 return map[string]string{"id": id}
}

2. 数据库集成

GoFr 内置了对��种数据库的支持,下面是用 MySQL 的示例:

func main() {
 app := gofr.New()
 
 // 配置数据库连接
 app.Config.Set("DB_HOST", "localhost")
 app.Config.Set("DB_USER", "root")
 app.Config.Set("DB_PASSWORD", "password")
 app.Config.Set("DB_NAME", "myapp")
 
 // 使用数据库
 app.GET("/users"func(ctx *gofr.Context) interface{} {
  var users []User
  err := ctx.DB().Find(&users).Error
  if err != nil {
   return ctx.Error(err)
  }
  return users
 })
}

高级特性

1. 中间件支持

GoFr 支持灵活的中间件系统,可以用于日志记录、认证等:

func authMiddleware(next gofr.Handler) gofr.Handler {
 return func(ctx *gofr.Context) interface{} {
  token := ctx.Header("Authorization")
  if token == "" {
   return ctx.Error(errors.New("unauthorized"))
  }
  // 验证 token
  return next(ctx)
 }
}

func main() {
 app := gofr.New()
 
 // 全局中间件
 app.Use(authMiddleware)
 
 // 路由特定中间件
 app.GET("/protected", protectedHandler, authMiddleware)
}

2. 服务发现与注册

GoFr 提供了与服务注册中心的集成支持:

func main() {
 app := gofr.New()
 
 // 配置服务发现
 app.Config.Set("SERVICE_NAME", "user-service")
 app.Config.Set("SERVICE_PORT", "8080")
 
 // 自动注册服务
 app.EnableServiceDiscovery()
 
 app.Start()
}

进阶功能

1. 配置管理

GoFr 提供了灵活的配置管理系统,支持多种配置源:

func setupConfig(app *gofr.App) {
    // 从环境变量加载配置
    app.Config.LoadFromEnv()
    
    // 从配置文件加载
    app.Config.LoadFromFile("config.yaml")
    
    // 动态配置
    app.Config.Set("APP_MODE", "development")
    
    // 获取配置
    appMode := app.Config.Get("APP_MODE")
    port := app.Config.GetInt("PORT")
}

2. 日志系统

内置结构化日志支持:

func loggerExample(ctx *gofr.Context) interface{} {
    // 不同级别的日志
    ctx.Logger.Info("处理请求", "path", ctx.Request.URL.Path)
    ctx.Logger.Debug("调试信息", "params", ctx.Request.URL.Query())
    ctx.Logger.Error("发生错误", "error", err)
    
    // 带结构化字段的日志
    ctx.Logger.With(
        "user_id", "123",
        "action", "login",
    ).Info("用户登录")
    
    return nil
}

3. 缓存集成

Redis 缓存使用示例:

func cacheExample(ctx *gofr.Context) interface{} {
    // 获取 Redis 客户端
    redis := ctx.Cache()
    
    // 设置缓存
    err := redis.Set("user:123", userData, time.Hour).Err()
    if err != nil {
        return ctx.Error(err)
    }
    
    // 获取缓存
    val, err := redis.Get("user:123").Result()
    if err != nil {
        return ctx.Error(err)
    }
    
    return val
}

4. 健康检查

实现健康检查端点:

func setupHealthCheck(app *gofr.App) {
    app.GET("/health"func(ctx *gofr.Context) interface{} {
        health := map[string]interface{}{
            "status": "UP",
            "timestamp": time.Now(),
            "services": map[string]string{
                "database": "healthy",
                "cache": "healthy",
                "queue": "healthy",
            },
        }
        
        // 检查数据库连接
        if err := ctx.DB().Ping(); err != nil {
            health["services"].(map[string]string)["database"] = "unhealthy"
            health["status"] = "DOWN"
        }
        
        return health
    })
}

高级应用场景

1. 消息队列集成

func setupMessageQueue(app *gofr.App) {
    // 配置 RabbitMQ 连接
    app.Config.Set("RABBITMQ_URL", "amqp://guest:guest@localhost:5672/")
    
    // 消息发布
    app.POST("/messages"func(ctx *gofr.Context) interface{} {
        msg := ctx.Request.FormValue("message")
        err := ctx.MessageQueue().Publish("notifications", []byte(msg))
        if err != nil {
            return ctx.Error(err)
        }
        return map[string]string{"status": "published"}
    })
    
    // 消息消费
    app.MessageQueue().Subscribe("notifications"func(msg []byte) {
        log.Printf("Received message: %s", string(msg))
    })
}

2. 缓存策略

func cacheStrategy(app *gofr.App) {
    // 多级缓存实现
    app.GET("/users/:id"func(ctx *gofr.Context) interface{} {
        id := ctx.PathParam("id")
        cacheKey := fmt.Sprintf("user:%s", id)
        
        // 尝试从本地缓存获取
        if data := localCache.Get(cacheKey); data != nil {
            return data
        }
        
        // 尝试从 Redis 获取
        if data, err := ctx.Cache().Get(cacheKey).Result(); err == nil {
            localCache.Set(cacheKey, data, time.Minute)
            return data
        }
        
        // 从数据库获取
        var user User
        if err := ctx.DB().First(&user, id).Error; err != nil {
            return ctx.Error(err)
        }
        
        // 更新缓存
        userData, _ := json.Marshal(user)
        ctx.Cache().Set(cacheKey, userData, time.Hour)
        localCache.Set(cacheKey, userData, time.Minute)
        
        return user
    })
}

3. 事件驱动架构

func setupEventSystem(app *gofr.App) {
    // 定义事件总线
    eventBus := gofr.NewEventBus()
    
    // 注册事件处理器
    eventBus.Subscribe("user.created"func(event gofr.Event) {
        // 发送欢迎邮件
        sendWelcomeEmail(event.Data.(User))
        
        // 初始化用户配置
        initializeUserSettings(event.Data.(User))
    })
    
    // 发布事件
    app.POST("/users"func(ctx *gofr.Context) interface{} {
        var user User
        if err := ctx.BindJSON(&user); err != nil {
            return ctx.Error(err)
        }
        
        if err := ctx.DB().Create(&user).Error; err != nil {
            return ctx.Error(err)
        }
        
        // 触发用户创建事件
        eventBus.Publish("user.created", user)
        
        return user
    })
}

性能调优

1. 内存优化

func memoryOptimization(app *gofr.App) {
    // 对象池使用
    pool := sync.Pool{
        New: func() interface{} {
            return &bytes.Buffer{}
        },
    }
    
    app.Use(func(next gofr.Handler) gofr.Handler {
        return func(ctx *gofr.Context) interface{} {
            buf := pool.Get().(*bytes.Buffer)
            buf.Reset()
            defer pool.Put(buf)
            
            // 使用缓冲区处理请求
            ctx.SetValue("buffer", buf)
            return next(ctx)
        }
    })
}

2. 并发控制

func concurrencyControl(app *gofr.App) {
    // 工作池实现
    workerPool := make(chan struct{}, 100)
    
    app.Use(func(next gofr.Handler) gofr.Handler {
        return func(ctx *gofr.Context) interface{} {
            select {
            case workerPool <- struct{}{}:
                defer func() { <-workerPool }()
                return next(ctx)
            case <-time.After(time.Second):
                return ctx.JSON(503, map[string]string{
                    "error": "Server too busy",
                })
            }
        }
    })
}

微服务通信

1. gRPC 集成

func setupGRPC(app *gofr.App) {
    // 定义 gRPC 服务
    server := grpc.NewServer()
    pb.RegisterUserServiceServer(server, &UserService{})
    
    // 启动 gRPC 服务器
    go func() {
        lis, err := net.Listen("tcp", ":50051")
        if err != nil {
            log.Fatalf("failed to listen: %v", err)
        }
        if err := server.Serve(lis); err != nil {
            log.Fatalf("failed to serve: %v", err)
        }
    }()
}

2. 服务间通信

func setupServiceCommunication(app *gofr.App) {
    // HTTP 客户端配置
    client := &http.Client{
        Timeout: time.Second * 5,
        Transport: &http.Transport{
            MaxIdleConns:        100,
            MaxIdleConnsPerHost: 100,
            IdleConnTimeout:     90 * time.Second,
        },
    }
    
    // 服务调用
    app.GET("/composite"func(ctx *gofr.Context) interface{} {
        var result struct {
            UserData    interface{} `json:"user_data"`
            OrderData   interface{} `json:"order_data"`
            ProductData interface{} `json:"product_data"`
        }
        
        // 并发调用多个服务
        var wg sync.WaitGroup
        wg.Add(3)
        
        go func() {
            defer wg.Done()
            resp, _ := client.Get("http://user-service/users/1")
            json.NewDecoder(resp.Body).Decode(&result.UserData)
        }()
        
        go func() {
            defer wg.Done()
            resp, _ := client.Get("http://order-service/orders/1")
            json.NewDecoder(resp.Body).Decode(&result.OrderData)
        }()
        
        go func() {
            defer wg.Done()
            resp, _ := client.Get("http://product-service/products/1")
            json.NewDecoder(resp.Body).Decode(&result.ProductData)
        }()
        
        wg.Wait()
        return result
    })
}

性能优化建议

  1. 连接池配置:
func optimizeConnections(app *gofr.App) {
    // 数据库连接池设置
    app.Config.Set("DB_MAX_OPEN_CONNS", 100)
    app.Config.Set("DB_MAX_IDLE_CONNS", 10)
    app.Config.Set("DB_CONN_MAX_LIFETIME", "1h")
    
    // Redis 连接池设置
    app.Config.Set("REDIS_POOL_SIZE", 100)
    app.Config.Set("REDIS_MIN_IDLE_CONNS", 10)
}
  1. 请求超时控制:
func timeoutMiddleware(next gofr.Handler) gofr.Handler {
    return func(ctx *gofr.Context) interface{} {
        ctx.Request.Context()
        timeoutCtx, cancel := context.WithTimeout(ctx.Request.Context(), 5*time.Second)
        defer cancel()
        
        ctx.Request = ctx.Request.WithContext(timeoutCtx)
        return next(ctx)
    }
}

部署最佳实践

  1. Docker 部署示例:
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY . .
RUN go build -o main ./cmd/main.go

FROM alpine:latest
WORKDIR /app
COPY --from=builder /app/main .
COPY configs/ configs/
EXPOSE 8080
CMD ["./main"]
  1. Kubernetes 配置示例:
apiVersion: apps/v1
kind: Deployment
metadata:
  name: gofr-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: gofr-service
  template:
    metadata:
      labels:
        app: gofr-service
    spec:
      containers:
      - name: gofr-service
        image: gofr-service:latest
        ports:
        - containerPort: 8080
        env:
        - name: DB_HOST
          valueFrom:
            configMapKeyRef:
              name: gofr-config
              key: db_host

最佳实践

  1. 项目结构组织
myservice/ ├── cmd/ │ └── main.go ├── internal/ │ ├── handlers/ │ ├── models/ │ └── services/ ├── configs/ └── tests/
  1. 错误���理
func handleError(err error, ctx *gofr.Context) interface{} {
 switch e := err.(type) {
 case *CustomError:
  return ctx.JSON(e.Status, e)
 default:
  return ctx.JSON(500, map[string]string{
   "error": "Internal Server Error",
  })
 }
}

测试最佳实践

1. 单元测试

func TestUserHandler(t *testing.T) {
    // 创建测试应用实例
    app := gofr.NewTestApp()
    
    // 模拟请求
    req := httptest.NewRequest("GET", "/users/123", nil)
    resp := app.Test(req)
    
    // 断言响应
    assert.Equal(t, http.StatusOK, resp.StatusCode)
    
    var user User
    err := json.NewDecoder(resp.Body).Decode(&user)
    assert.NoError(t, err)
    assert.Equal(t, "123", user.ID)
}

2. 集成测试

func TestIntegration(t *testing.T) {
    // 启动测试容器
    pool, err := dockertest.NewPool("")
    if err != nil {
        t.Fatalf("Could not connect to docker: %s", err)
    }
    
    // 运行 MySQL 容器
    mysql, err := pool.Run("mysql", "8.0", []string{
        "MYSQL_ROOT_PASSWORD=secret",
        "MYSQL_DATABASE=testdb",
    })
    if err != nil {
        t.Fatalf("Could not start mysql: %s", err)
    }
    
    // 清理资源
    defer pool.Purge(mysql)
    
    // 运行测试
    app := setupTestApp(mysql.GetPort("3306/tcp"))
    // ... 执行测试逻辑
}

监控与可观测性

1. Prometheus 指标集成

func setupMetrics(app *gofr.App) {
    // 注册自定义指标
    requestCounter := prometheus.NewCounterVec(
        prometheus.CounterOpts{
            Name: "http_requests_total",
            Help: "Total number of HTTP requests",
        },
        []string{"method", "path"},
    )
    
    // 中间件记录指标
    app.Use(func(next gofr.Handler) gofr.Handler {
        return func(ctx *gofr.Context) interface{} {
            requestCounter.WithLabelValues(
                ctx.Request.Method,
                ctx.Request.URL.Path,
            ).Inc()
            return next(ctx)
        }
    })
    
    // 暴露指标端点
    app.GET("/metrics", prometheusHandler())
}

2. 分布式追踪

func setupTracing(app *gofr.App) {
    // 初始化 Jaeger 客户端
    tracer, closer, err := jaeger.NewTracer(
        "gofr-service",
        jaeger.NewConstSampler(true),
        jaeger.NewUDPReporter("jaeger:6831"),
    )
    if err != nil {
        log.Fatal(err)
    }
    defer closer.Close()
    
    // 中间件添加追踪
    app.Use(func(next gofr.Handler) gofr.Handler {
        return func(ctx *gofr.Context) interface{} {
            span := tracer.StartSpan(ctx.Request.URL.Path)
            defer span.Finish()
            
            ctx.SetValue("trace", span)
            return next(ctx)
        }
    })
}

安全性建议

1. CORS 配置

func setupCORS(app *gofr.App) {
    app.Use(func(next gofr.Handler) gofr.Handler {
        return func(ctx *gofr.Context) interface{} {
            ctx.Response.Header().Set("Access-Control-Allow-Origin", "*")
            ctx.Response.Header().Set("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS")
            ctx.Response.Header().Set("Access-Control-Allow-Headers", "Content-Type,Authorization")
            
            if ctx.Request.Method == "OPTIONS" {
                return nil
            }
            
            return next(ctx)
        }
    })
}

2. 请求限流

func rateLimiter(app *gofr.App) {
    limiter := rate.NewLimiter(rate.Limit(100), 200)
    
    app.Use(func(next gofr.Handler) gofr.Handler {
        return func(ctx *gofr.Context) interface{} {
            if !limiter.Allow() {
                return ctx.JSON(429, map[string]string{
                    "error": "Too Many Requests",
                })
            }
            return next(ctx)
        }
    })
}

常见问题解决方案

1. 优雅关闭

func gracefulShutdown(app *gofr.App) {
    quit := make(chan os.Signal, 1)
    signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
    
    go func() {
        <-quit
        log.Println("Shutting down server...")
        
        ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
        defer cancel()
        
        if err := app.Shutdown(ctx); err != nil {
            log.Fatal("Server forced to shutdown:", err)
        }
    }()
}

2. 重试机制

func withRetry(operation func() errormaxRetries interror {
    var err error
    for i := 0; i < maxRetries; i++ {
        if err = operation(); err == nil {
            return nil
        }
        time.Sleep(time.Second * time.Duration(math.Pow(2, float64(i))))
    }
    return fmt.Errorf("failed after %d retries: %v", maxRetries, err)
}

注意事项与最佳实践

1. 配置管理注意事项

func configurationBestPractices() {
    // 1. 避免硬编码配置
    // 不推荐
    dbHost := "localhost"
    
    // 推荐
    dbHost := os.Getenv("DB_HOST")
    
    // 2. 使用配置验证
    func validateConfig(config *gofr.Config) error {
        required := []string{"DB_HOST", "DB_USER", "DB_PASSWORD"}
        for _, key := range required {
            if config.Get(key) == "" {
                return fmt.Errorf("missing required config: %s", key)
            }
        }
        return nil
    }
    
    // 3. 使用默认值
    port := config.GetIntDefault("PORT", 8080)
}

2. 错误处理最佳实践

// 1. 自定义错误类型
type AppError struct {
    Code    int    `json:"code"`
    Message string `json:"message"`
    Details string `json:"details,omitempty"`
}

// 2. 统一错误处理中间件
func errorHandler(app *gofr.App) {
    app.Use(func(next gofr.Handler) gofr.Handler {
        return func(ctx *gofr.Context) (result interface{}) {
            defer func() {
                if err := recover(); err != nil {
                    // 记录堆栈信息
                    stack := debug.Stack()
                    ctx.Logger.Error("panic recovered"
                        "error", err,
                        "stack", string(stack))
                    
                    result = ctx.JSON(500, AppError{
                        Code:    500,
                        Message: "Internal Server Error",
                    })
                }
            }()
            
            return next(ctx)
        }
    })
}

3. 性能优化注意事项

// 1. 合理使用连接池
func connectionPooling(app *gofr.App) {
    // 根据CPU核心数设置连接池
    numCPU := runtime.NumCPU()
    maxConns := numCPU * 4
    
    app.Config.Set("DB_MAX_OPEN_CONNS", maxConns)
    app.Config.Set("DB_MAX_IDLE_CONNS", numCPU)
}

// 2. 使用适当的缓冲区大小
func bufferSizing() {
    // 对于大文件处理,使用固定大小的缓冲区
    buffer := make([]byte, 32*1024) // 32KB buffer
    
    // 使用 sync.Pool 复用缓冲区
    bufferPool := sync.Pool{
        New: func() interface{} {
            return make([]byte, 32*1024)
        },
    }
}

4. 安全性注意事项

// 1. 输入验证
func validateInput(ctx *gofr.Context) {
    // 使用验证器
    validator := validator.New()
    
    type UserInput struct {
        Username string `validate:"required,min=3,max=32"`
        Email    string `validate:"required,email"`
        Password string `validate:"required,min=8"`
    }
    
    var input UserInput
    if err := ctx.BindJSON(&input); err != nil {
        return ctx.Error(err)
    }
    
    if err := validator.Struct(input); err != nil {
        return ctx.JSON(400, map[string]string{
            "error": "Invalid input",
            "details": err.Error(),
        })
    }
}

// 2. 安全头部设置
func securityHeaders(app *gofr.App) {
    app.Use(func(next gofr.Handler) gofr.Handler {
        return func(ctx *gofr.Context) interface{} {
            // 设置安全相关的 HTTP 头
            headers := ctx.Response.Header()
            headers.Set("X-Content-Type-Options", "nosniff")
            headers.Set("X-Frame-Options", "DENY")
            headers.Set("X-XSS-Protection", "1; mode=block")
            headers.Set("Strict-Transport-Security", "max-age=31536000; includeSubDomains")
            
            return next(ctx)
        }
    })
}

5. 部署注意事项

# Kubernetes 资源限制配置
apiVersion: apps/v1
kind: Deployment
metadata:
  name: gofr-service
spec:
  template:
    spec:
      containers:
      - name: gofr-service
        resources:
          requests:
            cpu: "100m"
            memory: "128Mi"
          limits:
            cpu: "500m"
            memory: "512Mi"
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 15
          periodSeconds: 20
        readinessProbe:
          httpGet:
            path: /ready
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 10

6. 日志最佳实践

func loggingBestPractices(app *gofr.App) {
    // 1. 结构化日志
    app.Use(func(next gofr.Handler) gofr.Handler {
        return func(ctx *gofr.Context) interface{} {
            startTime := time.Now()
            
            result := next(ctx)
            
            // 记录请求信息
            ctx.Logger.Info("request completed",
                "method", ctx.Request.Method,
                "path", ctx.Request.URL.Path,
                "duration", time.Since(startTime),
                "status", ctx.Response.Status(),
                "client_ip", ctx.ClientIP(),
                "user_agent", ctx.Request.UserAgent(),
            )
            
            return result
        }
    })
    
    // 2. 敏感信息处理
    type sensitiveData struct {
        Password string
        Token    string
    }
    
    func (s sensitiveData) MarshalLogObject(enc zapcore.ObjectEncoder) error {
        enc.AddString("password", "[REDACTED]")

总结

GoFr 框架作为一个现代化的 Go 微服务框架,具有以下显著优势:

  1. 简单易用

    • 零依赖设计,降低了学习和维护成本
    • 清晰的 API 设计,使开发者能够快速上手
    • 完善的文档和示例,加速开发流程
  2. 功能完整

    • 内置路由系统和中间件支持
    • 集成数据库、缓存、消息队列等常用组件
    • 提供服务发现、配置管理等微服务必备功能
  3. 性能优异

    • 经过优化的路由和中间件系统
    • 支持连接池和内存复用
    • 提供多种性能优化选项
  4. 安全可靠

    • 内置安全特性(CORS、限流等)
    • 完善的错误处理机制
    • 支持优雅关闭和故障恢复
  5. 可观测性

    • 集成 Prometheus 监控
    • 支持分布式追踪
    • 结构化日志系统
  6. 部署便捷

    • 提供 Docker 和 Kubernetes 支持
    • 完整的部署配置示例
    • 健康检查和就绪探针

最佳实践建议

  1. 在开始新项目时,建议:

    • 遵循项目结构规范
    • 使用配置管理
    • 实现完整的测试覆盖
  2. 在生产环境中,注意:

    • 合理配置资源限制
    • 实现监控和告警
    • 做好日志管理
    • 定期进行性能优化
  3. 在开发过程中,建议:

    • 使用错误处理最佳实践
    • 实现适当的安全措施
    • 保持代码简洁和可维护性

GoFr 框架为 Go 语言微服务开发提供了一个强大而完整的解决方案。通过合理使用其提供的特性和遵循最佳实践,开发者可以构建出高性能、可靠且易于维护的微服务应用。


南丞

赞赏二维码喜欢作者

阅读 1453
 
 
 
 
 
 
 
 
写留言
留言 4
  • golang 1.24已经完全支持动态路由了,不需要这类路由框架了。另外,个人觉得go-zero最好
    作者赞过
     
     
  • 习惯了zero了
    作者赞过
     
     
  • 服务注册依赖etcd还是别的啥?
    作者赞过
     
    服务注册默认使用的是Consul,不是etcd
     
已无更多数据
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/855003.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

R机器学习:朴素贝叶斯算法的理解与实操

最近又看了很多贝叶斯算法的一些文章,好多的文章对这个算法解释起来会放一大堆公式,对代数不好的人来说真的很头疼。本文尝试着用大白话写写这个算法,再做个例子,帮助大家理解和运用。Naive Bayes is a probabilistic machine learning algorithm based on the Bayes Theor…

[Linux]线程

线程 页表 每个进程都有一个虚拟地址空间,虚拟地址通过页表的映射找到对应的物理地址。那页表是如何完成虚拟地址到物理地址的映射的呢?其实一个程序在磁盘上的时候就以4KB为单位被划分成块,每一块称为页帧;而物理内存同样是以4KB为单位被划分,每一块称为页框。所以程序都…

Java框架 —— SpringMVC

MVC 分层MVC:Model View Controller(模型-视图-控制器)模型(Model):处理数据逻辑的部分;在web应用中,他通常包含与数据库交互的代码,负责数据的存储、检索和更新视图(View):将数据渲染为用户界面,视图只展示页面,不包含业务逻辑控制器(Controller):模型和视图…

2024-12-18 17 55 记录 Cambly trip`s summary and wher 1607b517085581159d14fe7750337be7

2024-12-18 17:55 记录 Cambly trip`s summary and where is the next ?https://tingwu.aliyun.com/doc/transcripts/g2y8qevxaayxnbeo?sl=1# 《2024-12-18 17:55 记录 Cambly trip`s summary and where is the next ?》1. 全文摘要 对话讲述了一个人通过使用美好的旅行来…

实验六 模板类、文件I/O和异常处理

1、实验任务一 Complex.hpp#pragma once#include <iostream> #include <stdexcept>// 声明 //////////////////////////////////////////////////// // 复数模板类声明 template<typename T> class Complex { public:Complex(T r = 0, T i = 0);Complex(cons…

免费设计Logo的新神器Slea.ai

使用Slea.ai,你可以在几分钟内设计出专业、高质量的Logo,支持多种场景应用,免费下载,实现自定义设计。品牌打造从未如此轻松!作为一名注重品牌形象的创作者或企业主,你是否苦于设计一款专业又独特的Logo?今天我要向大家推荐一个超级实用的网站——Slea.ai,它是一款免费的…

MOS管的寄生电容

我们经常看到,在电源电路中,功率MOS管的G极经常会串联一个小电阻,几欧姆到几十欧姆不等,那么这个电阻用什么作用呢? 这个电阻的作用有2个作用:限制G极电流,抑制振荡。 限制G极电流MOS管是由电压驱动的,是以G级电流很小,但是因为寄生电容的存在,在MOS管打开或关闭的时…

配置CentOS 7阿里yum源

备份yum源配置文件 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo_bakvi /etc/yum.repos.d/CentOS-Base.repo# CentOS-Base.repo # # The mirror system uses the connecting IP address of the client and the # update status of each mirror to …

源码信息收集

引子:上一篇主要介绍了与Web架构相关的信息收集,而在Web架构中有一至关重要的一环,那就是源码。Web应用中美观的ui、特色的功能全靠源码来实现,但同样的,几乎绝大多数与Web相关的漏洞都也都与其源码有关。而本篇则介绍几种常见的源码信息收集方式。附:完整笔记目录~ ps:…

标定和定位的关系

手眼标定手眼标定可以利用某真值位置和传感器观测位置对比得到外参。 关联本质上是外参不同引起的看同一外接参照物,认为自身运动轨迹的不同。位置如上观测同一建筑(三角形,上顶点是北方),真实轨迹(左图):是向北直行是在向正前方走世界坐标系->偏置传感器轨迹(中间图…