深入解析Go语言`errors`库:提升你的错误处理技能

深入解析Go语言`errors`库:提升你的错误处理技能

    • 引言
    • Go的错误处理简介
      • 错误作为值
      • `error`接口
      • 简单错误处理示例
    • `errors`包概览
      • 创建错误
      • 错误格式化
      • 错误检查
      • 示例:错误检查
    • 创建和使用自定义错误
      • 定义自定义错误类型
      • 使用自定义错误
      • 错误包装
      • 错误处理的灵活性
    • 错误检查和处理
      • 利用`errors.Is`进行精确错误检查
      • 使用`errors.As`找寻和处理错误类型
      • 错误处理策略
      • 示例:综合错误处理
    • 使用`errors`进行错误包装
      • 错误包装的优势
      • 如何进行错误包装
      • 错误链的检查和解包
      • 错误处理的最佳实践
      • 实战项目中的应用
    • `errors`在实战项目中的应用
      • 案例一:API服务错误处理
      • 案例二:微服务间的错误传播
      • 案例三:错误日志和监控
    • 错误处理的最佳实践
      • 1. 明确错误传播的责任
      • 2. 使用具体错误类型而非错误字符串
      • 3. 为错误添加上下文信息
      • 4. 避免过度包装错误
      • 5. 利用`errors.Is`和`errors.As`进行错误检查
      • 6. 在适当的地方处理错误
      • 7. 记录关键的错误信息
      • 8. 使用专门的错误处理函数和中间件
    • 结语

在这里插入图片描述

引言

在现代软件开发中,有效的错误处理是编写可靠、健壯和易于维护代码的关键。Go语言,作为一种旨在简化编程任务和提高效率的编程语言,通过其标准库中的errors包提供了一套简洁而强大的错误处理机制。与传统的异常处理机制不同,Go语言采用的是将错误作为一等公民来对待,意味着在函数之间传递和处理错误就像处理普通变量一样简单。

这种设计哲学不仅鼓励开发者显式地检查和处理每一个可能的错误场景,而且还使得错误处理逻辑更加清晰和可预测。在这篇文章中,我们将深入探讨errors包的各种使用方法和最佳实践。从基本的错误创建和检查到高级的错误处理技术,本文旨在为中级和高级Go开发者提供一个实战指南,帮助他们充分利用Go语言的错误处理能力,编写更加健壮和可维护的代码。

通过阅读本文,您将学会如何利用errors包来创建和管理错误,如何通过错误检查和处理提高代码的健壮性,以及如何使用错误包装来保留错误的上下文信息,从而使得错误调试和追踪变得更加容易。此外,我们还将通过一些实际案例来展示这些概念和技术是如何应用在真实的项目中的,从而帮助您更好地理解和掌握Go语言中的错误处理机制。

Go的错误处理简介

在Go语言中,错误处理被设计得非常简单直接,这主要归功于其核心理念之一:错误作为一等公民。这意味着在Go中,错误被视为正常的值,可以像任何其他类型的值那样被返回和处理。这种方法与许多其他编程语言中采用的异常处理机制有显著的不同,在那些语言中,错误(或异常)通常通过特殊的控制流结构来处理。

错误作为值

在Go中,当一个函数可能遇到错误情况时,它会返回两个值:一个是正常的返回值,另一个是error类型的值。如果一切顺利,错误值将为nil;如果发生了错误,错误值将包含有关错误的信息。这要求调用方检查返回的错误值是否为nil,从而决定下一步如何处理。

error接口

Go语言中的error类型是一个接口,定义如下:

type error interface {
    Error() string
}

任何实现了Error() string方法的类型都可以作为一个错误。这个方法返回一个描述错误的字符串,这是当打印错误值时通常看到的内容。通过这种方式,Go允许开发者创建自定义错误类型,提供了更多的灵活性和表达力。

简单错误处理示例

让我们看一个简单的错误处理例子,以便更好地理解这些概念:

package main

import (
    "errors"
    "fmt"
)

func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, errors.New("cannot divide by zero")
    }
    return a / b, nil
}

func main() {
    result, err := divide(10, 0)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    fmt.Println("Result:", result)
}

在这个例子中,divide函数尝试将两个数字相除,如果除数是0,就会返回一个错误。调用方检查返回的错误值,如果不是nil,就打印出错误信息。

errors包概览

Go语言的errors包提供了一些基础但极为重要的工具来辅助错误的创建和处理。这个包虽然小巧,功能却不可小觑,它使得在Go程序中处理错误成为了一项简单而直接的任务。

创建错误

errors包最基本的功能是创建新的错误。这可以通过errors.New函数实现,该函数接受一个字符串参数(描述错误的信息),并返回一个新的错误对象。这个新创建的错误对象实现了error接口,因此可以像任何其他错误一样被处理。

err := errors.New("this is an error message")
fmt.Println(err) // 输出: this is an error message

在实践中,errors.New通常用于定义包级别的错误变量,这些错误变量可以在整个包中重复使用。

错误格式化

另一个实用的工具是fmt.Errorf函数,它提供了一种创建格式化错误信息的方式。这个函数工作方式类似于fmt.Sprintf,除了它返回一个错误对象而不是字符串。这使得在需要将动态数据包含在错误信息中时非常有用。

fileName := "example.txt"
err := fmt.Errorf("failed to open file %q", fileName)
fmt.Println(err) // 输出: failed to open file "example.txt"

fmt.Errorf的使用提升了错误信息的表达力,使得错误更加具体和有用。

错误检查

在Go 1.13中,errors包引入了IsAs函数,它们提供了一种更灵活的错误检查机制。这些函数使得比较错误和检查错误类型变得更加简单和直观,尤其是在处理包装过的错误时。

  • errors.Is函数用于检查错误链中是否存在特定的错误值。这对于判断错误是否等于某个已知错误非常有用,即使错误被多层包装。

  • errors.As函数用于检查错误链中是否存在特定类型的错误,并且如果存在,它可以提取错误值。这使得在需要根据错误的类型采取不同行动时非常有用。

示例:错误检查

var ErrNotFound = errors.New("not found")

// somewhere in the code
if errors.Is(err, ErrNotFound) {
    // handle the not found error
}

通过errors.Iserrors.As,Go提供了一种强大的机制来处理复杂的错误情况,让开发者能够更精确地控制错误处理的逻辑。

创建和使用自定义错误

在Go语言中,自定义错误不仅能提供错误发生的具体信息,还能携带更多上下文,使得错误处理更加灵活和强大。利用errors包和Go的接口机制,我们可以定义自定义错误类型,进而提高错误管理的效率和可读性。

定义自定义错误类型

自定义错误通常通过实现error接口来创建,这需要定义一个结构体并为其实现Error()方法。这种方法允许错误携带额外的上下文信息,例如错误发生的位置、相关的数据等,使得调试和错误处理更加直接。

type MyError struct {
    Msg string
    File string
    Line int
}

func (e *MyError) Error() string {
    return fmt.Sprintf("%s:%d: %s", e.File, e.Line, e.Msg)
}

使用自定义错误

一旦定义了自定义错误类型,就可以在需要报告错误的地方创建和返回这些错误的实例。这使得错误信息更加丰富,有助于错误的调试和处理。

func doSomething() error {
    // 模拟错误发生
    return &MyError{
        Msg:  "something failed",
        File: "somefile.go",
        Line: 42,
    }
}

func main() {
    err := doSomething()
    if err != nil {
        fmt.Println(err)
    }
}

错误包装

自Go 1.13起,fmt.Errorf支持通过%w动词来包装错误,这为错误提供了更多上下文。错误包装允许你保留原始错误的同时,添加额外的说明或上下文。这对于在错误传播过程中保留错误链非常有用。

func doAnotherThing() error {
    err := doSomething()
    if err != nil {
        // 包装原始错误,添加更多上下文
        return fmt.Errorf("doAnotherThing failed: %w", err)
    }
    return nil
}

通过这种方式,当错误最终被处理时,我们不仅能获取到当前错误的上下文,还能追踪到错误链中更深层次的原因。

错误处理的灵活性

使用自定义错误和错误包装提高了错误处理的灵活性。例如,通过errors.As函数,我们可以检查错误是否为特定类型的自定义错误,并根据需要访问错误中的额外信息。

err := doAnotherThing()
var myErr *MyError
if errors.As(err, &myErr) {
    fmt.Println("Custom error occurred:", myErr)
}

这种模式极大地增加了错误处理的能力,允许更精细和定制化的错误响应策略,使得代码更加健壮且易于维护。

错误检查和处理

在Go语言中,错误检查和处理是编写健壮且可维护代码的关键环节。通过使用errors包提供的工具,开发者可以实现精准的错误控制逻辑,这对于构建高质量的Go应用程序至关重要。

利用errors.Is进行精确错误检查

errors.Is函数是一个强大的工具,它允许开发者检查一个错误值是否与特定错误相等或者说“等价”。这在处理错误时非常有用,尤其是当错误可能被多次包装的情况下。errors.Is能够透明地解开错误包装,直到找到与指定错误相等的错误值。

if errors.Is(err, os.ErrNotExist) {
    fmt.Println("文件不存在")
}

在上述示例中,即使err是一个包装了多层的错误,只要错误链中有任何一个错误与os.ErrNotExist相等,errors.Is就会返回true

使用errors.As找寻和处理错误类型

errors.Is相比,errors.As函数旨在检查错误值是否为特定类型,并且如果是,它还可以提取该错误值。这对于当你需要根据错误的具体类型来采取不同的错误处理策略时非常有用。

var pathError *os.PathError
if errors.As(err, &pathError) {
    fmt.Println("发生了路径错误:", pathError.Path)
}

在这个例子中,如果err*os.PathError类型或包含该类型的错误,errors.As会将err转换为该类型,并赋值给pathError变量,然后你就可以访问pathError的具体字段了。

错误处理策略

良好的错误处理策略不仅能提高程序的健壮性,还能提高代码的可读性和可维护性。以下是一些推荐的错误处理策略:

  • 及早失败,避免深层嵌套:当检测到错误时,应该尽早返回错误,而不是使用深层的嵌套来处理错误。
  • 错误包装:为错误添加更多上下文信息,这可以通过fmt.Errorf%w格式化动词来实现。这有助于错误的追踪和调试。
  • 自定义错误类型:当标准的错误类型不足以表达错误的上下文时,考虑定义自定义错误类型。
  • 错误检查:使用errors.Iserrors.As精确控制错误的检查和处理。

示例:综合错误处理

以下是一个结合了多个错误处理技巧的实例,展示了如何在实际应用中有效地管理和处理错误。

func processFile(filename string) error {
    _, err := os.Open(filename)
    if err != nil {
        // 错误包装,添加上下文信息
        return fmt.Errorf("打开文件 %s 失败: %w", filename, err)
    }
    // 文件处理逻辑...
    return nil
}

func main() {
    err := processFile("不存在的文件.txt")
    if err != nil {
        if errors.Is(err, os.ErrNotExist) {
            fmt.Println("文件不存在。")
        } else {
            fmt.Println("未知错误:", err)
        }
    }
}

通过使用这些技巧和工具,Go开发者可以构建出更加健壮、可靠且易于维护的应用程序。

使用errors进行错误包装

错误包装是Go语言中一个强大的特性,它允许开发者在保持错误原始信息的同时,添加额外的上下文。这不仅有助于错误的调试,还可以让错误处理变得更加灵活和详细。从Go 1.13版本开始,通过fmt.Errorf函数和其%w动词,Go标准库提供了对错误包装的官方支持。

错误包装的优势

错误包装的主要优势在于它允许维护一个错误链,这个错误链详细记录了从错误发生点到当前处理点的整个调用路径。这使得开发者在调试时能够追踪到错误的原始来源,而不仅仅是在最终处理点得到一个抽象的错误信息。

如何进行错误包装

使用fmt.Errorf%w格式化占位符可以创建一个包含原始错误的新错误。这样,新的错误信息提供了额外的上下文,而通过errors.Unwrap函数,我们仍然可以访问到被包装的原始错误。

func readFile(path string) error {
    _, err := os.ReadFile(path)
    if err != nil {
        // 使用 %w 包装错误,添加额外的上下文信息
        return fmt.Errorf("read file %s failed: %w", path, err)
    }
    return nil
}

错误链的检查和解包

当错误被包装后,可以使用errors.Iserrors.As进行错误链的检查,这两个函数可以透明地处理错误链,识别出是否包含特定的错误或错误类型。

同时,errors.Unwrap函数可以用来逐层解包错误,获取错误链中的下一个错误,直到没有更多被包装的错误为止。

err := readFile("non-existent-file.txt")
if errors.Is(err, os.ErrNotExist) {
    fmt.Println("文件不存在")
} else {
    fmt.Println("发生了其他错误:", err)
}

错误处理的最佳实践

在实践中,合理利用错误包装可以极大提高程序的错误处理能力和代码的可维护性。开发者应该遵循以下最佳实践:

  • 当向上层传递错误时,考虑添加有意义的上下文信息,使得错误更容易被理解和调试。
  • 使用errors.Iserrors.As对错误链进行检查,以准确判断错误类型或错误值。
  • 在需要解包错误以获取更多信息时,使用errors.Unwrap

实战项目中的应用

在实际项目中,正确地使用错误包装和处理可以帮助团队更快地定位和修复问题,尤其是在复杂的系统中。通过在错误中嵌入足够的上下文信息,开发者可以快速理解错误发生的背景和原因,从而制定出更有效的解决方案。

errors在实战项目中的应用

在实战开发中,正确地使用errors包不仅能提高代码的健壮性,还能增强错误处理的清晰度和可维护性。接下来,我们将通过几个实战案例,展示如何在项目中有效地利用errors包进行错误处理。

案例一:API服务错误处理

在构建API服务时,准确地向客户端报告错误信息是至关重要的。利用errors包,我们可以定义一系列标准化错误,并通过错误包装添加额外的上下文信息,从而使客户端能够根据错误代码或消息采取相应的措施。

// 定义API错误
var ErrUserNotFound = errors.New("用户不存在")

// GetUser从数据库中获取用户信息
func GetUser(id string) (*User, error) {
    // 模拟用户不存在的错误
    return nil, fmt.Errorf("获取用户 %s 失败: %w", id, ErrUserNotFound)
}

// API处理函数
func UserHandler(w http.ResponseWriter, r *http.Request) {
    user, err := GetUser("some-user-id")
    if err != nil {
        if errors.Is(err, ErrUserNotFound) {
            http.Error(w, "用户不存在", http.StatusNotFound)
            return
        }
        http.Error(w, "内部服务器错误", http.StatusInternalServerError)
        return
    }
    // 正常处理用户信息
}

在这个案例中,通过检查错误是否为ErrUserNotFound,我们可以给客户端提供具体的错误状态码和信息,从而提升用户体验。

案例二:微服务间的错误传播

在微服务架构中,服务间的调用可能会引入额外的错误处理复杂度。使用errors包,我们可以在服务间传递具有丰富上下文的错误信息,使得错误定位更加迅速。

假设服务A调用服务B,服务B发生了一个错误,服务B可以将错误包装后返回给服务A,服务A再根据错误类型进行相应处理或将错误信息传递给客户端。

// 服务B中
func ServiceBFunction() error {
    // 模拟数据库查询错误
    return fmt.Errorf("查询数据库失败: %w", errors.New("连接超时"))
}

// 服务A中调用服务B
func CallServiceB() error {
    err := ServiceBFunction()
    if err != nil {
        // 包装并添加更多上下文信息
        return fmt.Errorf("调用服务B失败: %w", err)
    }
    return nil
}

案例三:错误日志和监控

在应用程序中添加错误日志和监控是发现和解决问题的关键。通过errors包的错误包装功能,我们可以将错误日志记录得更加详细,同时保留完整的错误链,这对于后续的错误分析和处理至关重要。

func ProcessData() error {
    err := someOperation()
    if err != nil {
        // 包装错误,记录额外的执行上下文
        wrappedErr := fmt.Errorf("处理数据时发生错误: %w", err)
        log.Error(wrappedErr) // 使用日志系统记录错误
        return wrappedErr
    }
    return nil
}

在这个案例中,当someOperation函数发生错误时,我们不仅记录了原始错误,还通过包装添加了当前操作的上下文信息,这大大提高了日志的价值。

错误处理的最佳实践

在Go语言中,正确地处理错误是保证代码质量的关键。以下是一些推荐的错误处理最佳实践,这些实践可以帮助开发者写出更健壮、易于维护和理解的代码。

1. 明确错误传播的责任

当设计函数和方法时,明确哪些操作应该返回错误,哪些应该处理错误。这有助于保持错误处理逻辑的一致性,并减少在错误传播链中不必要的错误检查。

2. 使用具体错误类型而非错误字符串

尽量避免使用错误字符串来传递错误信息。相反,使用errors.New或自定义错误类型来表示特定的错误情况。这不仅使得错误更易于检查(使用errors.Iserrors.As),还使得国际化和本地化处理更为方便。

3. 为错误添加上下文信息

使用fmt.Errorf%w动词来包装错误,为错误添加上下文信息。这使得错误更具可读性,并帮助开发者在发生错误时快速定位问题。

4. 避免过度包装错误

虽然为错误添加上下文信息很有用,但过度包装错误可能会导致错误信息过于冗长和复杂,从而使得调试变得更加困难。合理地包装错误,并确保错误信息清晰、简洁。

5. 利用errors.Iserrors.As进行错误检查

利用errors.Iserrors.As来检查错误,而不是直接与特定错误实例进行比较。这样可以更灵活地处理错误,特别是在错误被包装的情况下。

6. 在适当的地方处理错误

避免错误在没有得到适当处理的情况下传播太远。在错误发生的地方立即处理错误通常是最佳做法,除非确实需要将错误传递给调用者处理。

7. 记录关键的错误信息

对于关键操作中发生的错误,应该记录足够的错误信息,包括操作的上下文。这对于后续的错误分析和问题解决至关重要。

8. 使用专门的错误处理函数和中间件

在复杂的应用或框架中,考虑使用专门的错误处理函数或中间件来集中处理错误。这样可以减少代码冗余,并提高错误处理的一致性和效率。

结语

Go语言的errors包提供了强大而灵活的工具,帮助开发者有效地管理和处理错误。通过本文的介绍和案例分析,我们看到了在实战开发中应用errors包的各种方式,以及遵循错误处理最佳实践的重要性。正确地使用这些工具和技术,可以显著提升代码质量,增强应用的健壮性和可维护性。

记住,良好的错误处理不仅能够提高用户体验,还能在开发过程中节省大量时间。希望本文能帮助你在Go语言的错误处理旅程中迈出坚实的一步。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【python 装饰器 - 重试】做一个简易重试装饰器,如果函数执行错误则会自动重新执行,可设置重试次数,对爬虫比较友好

文章日期:2024.03.19 使用工具:Python 类型:装饰器 文章全程已做去敏处理!!! 【需要做的可联系我】 AES解密处理(直接解密即可)(crypto-js.js 标准算法)&…

数据库国产化探究及升级改造过程指导

一、背景 在信创“自主可控”的浪潮下,政企行业首当其冲,基于国产化信创的要求,本部门某业务后端应用也需要针对分析开源组件的风险和开源协议的商业应用限制;能用国产化替代的评估后尽可替代割接,本期针对传统数据库…

控制学习_正弦波无刷直流力矩电机建模、控制带宽讨论与选择

无刷电机通过电子换向器实现定子的磁场旋转,去电刷后使用寿命大幅提升,是现在更流行的选择。三相无刷电机则是无刷电机中比较流行的一款。三相无刷电机的驱动方式有多种,最简单的被称为梯形波驱动、方波驱动或正弦波驱动。而正弦波驱动技术可…

SpringBoot 监控 SQL 运行情况

1 基本概念 2 添加依赖 3 配置相关属性 4 sql监控 5 慢sql记录 6 spring 监控 7 去 Ad(广告) 8 获取 Druid 的监控数据 1 基本概念 Druid 是Java语言中最好的数据库连接池。 虽然 HikariCP 的速度稍快,但是,Druid能够提…

Elasticsearch:使用 OpenAI、LangChain 和 Streamlit 的基于 LLM 的 PDF 摘要器和 Q/A 应用程序

嘿! 您是否曾经感觉自己被淹没在信息的海洋中? 有这么多的书要读,而时间却这么少,很容易就会超负荷,对吧? 但猜猜怎么了? 你可以使用大型语言模型创建自定义聊天机器人,该模型可以帮…

极客早报第2期:93年副所长入警9年满头白发;黑马情侣提车;早上六点起床跟八点起床的区别

一分钟速览新闻点! 每日简报 93年副所长入警9年满头白发黑马情侣提车早上六点起床跟八点起床的区别男子被流浪猫绊倒投喂者赔24万鸡骨泥运用于淀粉肠中不算违规路边卖淀粉肠阿姨主动出示声明书她和智障哥哥唯一合照是别人拍的卫健委回应卖血猝死广西辟谣“核潜艇生…

01.Linked-List-Basic

1. 链表简介 1.1 链表定义 链表(Linked List):一种线性表数据结构。它使用一组任意的存储单元(可以是连续的,也可以是不连续的),来存储一组具有相同类型的数据。 简单来说,「链表」…

2.1(TCP)

TCP—传输控制协议 是一种面向连接的可靠传输协议。可靠、有序、无丢弃和不重复。 特点: TCP是面向连接(虚连接)的传输层协议每一条TCP连接有且只能有两个端点。可靠、有序、无丢弃和不重复。TCP协议提供全双工通讯。 发送缓存 存放发送方…

phpStudy安装thinkCMF8时,如何解决服务器rewrite和APIrewrite不支持的问题

解决步骤: 一:服务器rewrite 点击后面的问号跳转到官方文档链接: 复制红框内的代码 打开phpstudy,找到配置的站点,点击管理,找到伪静态 点击确认保存即可。 phpstudy会自动重启站点。 此时,…

Hive-技术补充-ANTLR词法语法分析

一、背景 要清晰的理解一条Hql是如何编译成MapReduce任务的,就必须要学习ANTLR。下面是ANTLR的官方网址,下面让我们一起来跟着官网学习吧 ANTLR 二、ANTLR元语言 1、启发 静下来想想,一门语言有什么组成,比如我们的中文&…

FPGA高端项目:FPGA基于GS2971+GS2972架构的SDI视频收发+GTX 8b/10b编解码SFP光口传输,提供2套工程源码和技术支持

目录 1、前言免责声明 2、相关方案推荐本博主所有FPGA工程项目-->汇总目录本博已有的 SDI 编解码方案本方案的SDI接收发送本方案的SDI接收图像缩放应用本方案的SDI接收纯verilog图像缩放纯verilog多路视频拼接应用本方案的SDI接收HLS图像缩放HLS多路视频拼接应用本方案的SDI…

基于Logstash的动态表同步方案

文章目录 引言I 动态表的同步1.1 利用数据库函数进行动态表名拼接1.2 利用shell脚步进行动态日期表名拼接1.3 方案小结II 增量同步III 同步多数据表引言 基于Logstash由SQLServer向Elasticsearch同步数据,兼容SQL Server 2005,在连接数据库时,url后面加上一个encrypt=false或…

【Mysql数据库基础02】单行函数、排序

单行函数、排序 1 单行函数1.1 常用函数1.1.1 length 字符串的长度1.1.2 ifnull 判断表达式是否为空 1.2 字符函数1.2.1 substr 提取自串1.2.2 转换大小写1.2.3 instr 返回起始索引1.2.4 trim 去除两端指定字符1.2.5 lpad 左填充指定长度 1.3 数学函数1.3.1 round 四舍五入1.3.…

Vue.js中使用Web Workers来创建一个秒表

在Vue.js中使用Web Workers来创建一个秒表应用可以提高性能,因为Web Workers可以在后台线程中运行,不阻塞主线程。下面是一个简单的Vue.js秒表应用的示例,该应用使用Web Worker来执行计时功能。 首先,我们创建一个Web Worker文件…

【iOS】——Blocks

文章目录 前言一、Blocks概要1.什么是Blocks 二、Block模式1.block语法2.block类型变量3.截获自动变量值4._Block修饰符5.截获的自动变量 三、Blocks的实现1.Block的实质2.截获自动变量值3._Block说明符4.Block存储域 前言 一、Blocks概要 1.什么是Blocks Blocks是C语言的扩…

国创证券|超五成私募看好AI成为年度行情主线

3月18日,2024年度全球游戏开发者大会(GDC)与英伟达GPU(图形处理器)技能大会(GTC)举行,出资者关于A股商场的“人工智能”也给予了更多等待。 2月6日至3月15日期间,商场对…

使用 nsenter 排查容器网络问题

需求 我想进入容器中执行 curl 命令探测某个地址的连通性,但是容器镜像里默认没有 curl 命令。我这里是一个内网环境不太方便使用 yum 或者 apt 安装,怎么办? 这个需求比较典型,这里教大家一个简单的方法,使用 nsent…

Linux/Bizness

Enumeration nmap 用 nmap 扫描了常见的端口,发现对外开放了22,80,443 ┌──(kali㉿kali)-[~] └─$ nmap 10.10.11.252 Starting Nmap 7.93 ( https://nmap.org ) at 2024-03-08 01:21 EST Nmap scan report for 10.10.11.252 Host is up (0.36s latency). Not…

H266开源视频编码器VVENC现状

VVenC 是由 Fraunhofer HHI 研究团队开发的,主要是视频编码系统组。HHI 是欧洲最大的研究组织 Fraunhofer 协会的成员,该协会是德国的一个大型非营利性组织。源代码在: https://github.com/fraunhoferhhi/vvenc VVenC几乎与H.266视频标准同时…

什么是VR虚拟现实防火体验馆|VR设备购买|元宇宙文旅

VR虚拟现实防火体验馆是利用虚拟现实(VR)技术打造的一个模拟火灾场景的体验空间。通过虚拟现实头盔和交互设备,参与者可以在虚拟环境中感受和学习如何正确面对火灾,并进行逃生和自救。 这种虚拟现实防火体验馆通常会模拟真实的火灾…