当前位置: 首页 > news >正文

【go语言规范】关于接口设计

抽象应该被发现,而不是被创造。为了避免不必要的复杂性,需要时才创建接口,而不是预见到需要它,或者至少可以证明这种抽象是有价值的。
“The bigger the interface, the weaker the abstraction.
不要用接口进行设计,要发现他们
——rob pike
作为一个常用java的程序员,在创建具体类型之前创建接口是很自然的,但是go不应该这样工作。
创建接口是为了创建抽象。当编程时遇到抽象,主要的注意事项时记住应该发现抽象,而不是创建抽象。
这意味着如果没有直接的理由,不应该在代码中创建抽象。
我们不应该用接口来设计,而应该等待具体的需求。
应该在需要的时候创建一个接口,而不是预见到可能需要他的时候。
如果没有充足的理由添加接口,也不清楚接口如何使代码变得更好,那么我们应该质疑这个接口的目的。为什么不直接调用实现呢?
哲学: 不要试图抽象地解决问题,而适应解决现在必须解决的问题。
如果不清楚接口如何是代码变得更好,我们应该考虑删除它,以使代码更简单。
哲学的哲学:不要抽象,干实事。

Go 语言接口设计原则

接口要小而精准
单一职责原则
// 不推荐 - 接口过大
type Storage interface {
Save(data interface{}) error
Delete(id string) error
Update(data interface{}) error
Get(id string) interface{}
List() []interface{}
}
// 推荐 - 拆分成小接口
type Writer interface {
Save(data interface{}) error
}
type Reader interface {
Get(id string) interface{}
}

以使用者为中心
接口应该在使用处定义
type CustomerService struct {
// 在需要的地方定义接口
store customerStorer
}
// 最小化接口定义
type customerStorer interface {
Store(Customer) error
}

组合优于继承
通过小接口组合
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
// 组合接口
type ReadWriter interface {
Reader
Writer
}

遵循 Go 的惯例
使用动词+er命名
type Stringer interface {
String() string
}
type Handler interface {
Handle(msg Message) error
}

接口隔离原则
客户端不应依赖它不使用的方法
// 不推荐
type FileProcessor interface {
Open(name string) error
Read(b []byte) (n int, err error)
Write(b []byte) (n int, err error)
Close() error
}
// 推荐
type FileReader interface {
Read(b []byte) (n int, err error)
}
type FileWriter interface {
Write(b []byte) (n int, err error)
}

最佳实践

  1. 保持接口小巧
    // 好的实践
    type Logger interface {
    Log(message string) error
    }
    // 而不是
    type Logger interface {
    Log(message string) error
    Logf(format string, args …interface{}) error
    Debug(message string)
    Error(message string)
    // … 更多方法
    }

  2. 使用抽象接口
    // 具体的实现
    type Customer struct {
    ID string
    Name string
    }
    // 抽象的接口
    type CustomerFinder interface {
    FindCustomer(id string) (*Customer, error)
    }

  3. 避免接口污染
    // 不推荐
    type Config interface {
    // 过多的方法导致实现困难
    Database() string
    APIKey() string
    Timeout() time.Duration
    MaxRetries() int
    CacheSize() int
    // …更多配置项
    }
    // 推荐
    type DatabaseConfig interface {
    Database() string
    }
    type APIConfig interface {
    APIKey() string
    }

注意事项
显式优于隐式
Go 的接口是隐式实现的
但应该在文档中明确说明接口的期望行为
面向接口编程
依赖接口而不是具体实现
便于测试和模拟
避免过度设计
不要为了接口而接口
从实际需求出发设计接口
注意性能影响
接口调用会有少量性能开销
在性能关键路径上要谨慎使用
以上原则可以帮助我们设计出更好的 Go 接口,使代码更加灵活、可维护和可测试。

什么是接口污染?我们如何避免接口污染?

接口污染及其避免方法
接口污染(Interface Pollution)是指创建了不必要的或过大的接口,导致代码复杂性增加和维护困难的情况。
接口污染的表现形式

1. 过大的接口

// 不好的示例 - 接口污染
type Storage interface {
CreateCustomer(Customer) error
UpdateCustomer(Customer) error
DeleteCustomer(string) error
GetCustomer(string) (Customer, error)
ListCustomers() ([]Customer, error)
CreateOrder(Order) error
UpdateOrder(Order) error
DeleteOrder(string) error
// … 更多方法
}

2. 不必要的抽象

// 不好的示例 - 过度抽象
type StringFormatter interface {
Format(string) string
}
// 这种简单操作不需要接口
func ProcessString(formatter StringFormatter, s string) string {
return formatter.Format(s)
}

如何避免接口污染

1. 遵循接口隔离原则

// 好的示例 - 小而专注的接口
type CustomerReader interface {
GetCustomer(id string) (Customer, error)
}
type CustomerWriter interface {
CreateCustomer(Customer) error
UpdateCustomer(Customer) error
}
// 如果需要同时读写,可以组合接口
type CustomerStorage interface {
CustomerReader
CustomerWriter
}

2. 在使用处定义接口

// 好的示例 - 接口在使用处定义
type CustomerService struct {
// 只定义需要的方法
store customerStorer
}
type customerStorer interface {
StoreCustomer(Customer) error
}

3. 保持接口小巧精简

// 好的示例 - 最小化接口
type Logger interface {
Log(message string) error
}
// 具体实现可以有更多方法
type FileLogger struct {
path string
}
func (f *FileLogger) Log(message string) error {
// 实现日志记录
return nil
}
func (f *FileLogger) Close() error {
// 额外的方法
return nil
}

4. 根据实际需求设计

// 好的示例 - 基于实际需求的接口
type PaymentProcessor interface {
Process(payment Payment) error
}
// 不同的支付方式实现这个接口
type StripePayment struct{}
type PayPalPayment struct{}

接口设计最佳实践
单一职责
每个接口应该只表达一个清晰的概念
避免创建"万能"接口
显式依赖
明确声明所需的依赖
避免隐式依赖
基于需求驱动
等到真正需要时才创建接口
避免过度设计
持续重构
定期审查接口设计
及时拆分过大的接口
示例:重构污染的接口
// 原始污染的接口
type UserService interface {
CreateUser(User) error
UpdateUser(User) error
DeleteUser(string) error
GetUser(string) (User, error)
AuthenticateUser(string, string) bool
ResetPassword(string) error
}
// 重构后的小接口
type UserCreator interface {
CreateUser(User) error
}
type UserUpdater interface {
UpdateUser(User) error
}
type UserAuthenticator interface {
AuthenticateUser(string, string) bool
}
// 根据实际需求组合接口
type UserManager struct {
creator UserCreator
auth UserAuthenticator
}

通过以上方法,我们可以有效避免接口污染,使代码更加清晰、可维护和可测试。

我们不应该在生产端创建接口,同时创建具体的实现。这是c#和 Java的习惯 。

由于应该发现抽象而不是创建抽象,这意味着生产者不能强制所有客户端使用给定的抽象,相反,有客户来决定他是否需要某种形式的抽象,然后为他的需求确定最佳的抽象级别。

在 Go 中平衡抽象与具体实现

  1. 遵循 YAGNI 原则(You Ain’t Gonna Need It)
    不好的做法
    // 过度抽象的接口
    type CustomerStorage interface {
    StoreCustomer(customer Customer) error
    GetCustomer(id string) (Customer, error)
    UpdateCustomer(customer Customer) error
    DeleteCustomer(id string) error
    GetAllCustomers() ([]Customer, error)
    GetCustomersWithoutContract() ([]Customer, error)
    GetCustomersWithNegativeBalance() ([]Customer, error)
    // 可能用不到的方法…
    }

好的做法
// 根据实际需求定义小接口
type CustomerReader interface {
GetCustomer(id string) (Customer, error)
}
type CustomerWriter interface {
StoreCustomer(customer Customer) error
}

  1. 使用组合而不是继承
    // 基础接口
    type Reader interface {
    Read(p []byte) (n int, err error)
    }
    type Writer interface {
    Write(p []byte) (n int, err error)
    }
    // 按需组合
    type ReadWriter interface {
    Reader
    Writer
    }

  2. 在使用处定义接口
    type CustomerService struct {
    // 只定义服务真正需要的方法
    store interface {
    GetCustomer(id string) (Customer, error)
    StoreCustomer(Customer) error
    }
    }

  3. 使用适配器模式保持代码整洁
    // 具体实现
    type PostgresDB struct {
    // …
    }
    // 适配器
    type CustomerStorageAdapter struct {
    db *PostgresDB
    }
    func (a *CustomerStorageAdapter) GetCustomer(id string) (Customer, error) {
    // 转换调用
    return a.db.FindCustomerByID(id)
    }

  4. 分层设计
    // 领域模型
    type Customer struct {
    ID string
    Name string
    Balance float64
    }
    // 仓储接口
    type CustomerRepository interface {
    Find(id string) (*Customer, error)
    Save(customer *Customer) error
    }
    // 服务层
    type CustomerService struct {
    repo CustomerRepository
    }

  5. 关键设计原则
    按需抽象
    先写具体实现
    当需要多个实现时再抽象
    保持简单

// 简单直接的接口
type Printer interface {Print(content string) error
}

面向行为

// 描述行为而不是状态
type PaymentProcessor interface {Process(payment Payment) error
}
  1. 代码整洁性的保持
    明确的职责划分
// 清晰的包结构
project/
├── domain/       // 领域模型
├── repository/   // 数据访问
├── service/      // 业务逻辑
└── api/          // 接口层

统一的错误处理

// 定义领域错误
type NotFoundError struct {ID string
}
func (e *NotFoundError) Error() string {return fmt.Sprintf("customer %s not found", e.ID)
}

良好的命名约定

type CustomerFinder interface {// 动词+名词的方法命名FindByID(id string) (*Customer, error)
}

总结:
从具体实现开始
当有多个实现需求时再抽象
保持接口小而精确
使用组合来构建复杂接口
在实际使用处定义接口
通过清晰的项目结构保持代码整洁
这样可以在不过度抽象的同时,保持代码的可读性和可维护性。

在 Go 语言中,这确实是一个值得讨论的设计问题。一般来说,在生产者端定义接口确实不是最佳实践。让我解释原因:
不好的设计(当前代码)
package store
// 在生产者包中定义大而全的接口
type CustomerStorage interface {
StoreCustomer(customer Customer) error
GetCustomer(id string) (Customer, error)
UpdateCustomer(customer Customer) error
GetAllCustomers() ([]Customer, error)
GetCustomersWithoutContract() ([]Customer, error)
GetCustomersWithNegativeBalance() ([]Customer, error)
}

更好的设计方式
在消费者端定义接口
package service
// 只定义服务需要的方法
type customerStore interface {
GetCustomer(id string) (Customer, error)
StoreCustomer(Customer) error
}
type CustomerService struct {
store customerStore
}

生产者端只提供具体实现
package store
type PostgresStore struct {
// … 具体实现细节
}
func (p *PostgresStore) GetCustomer(id string) (Customer, error) {
// 实现获取客户的逻辑
return Customer{}, nil
}
func (p *PostgresStore) StoreCustomer(c Customer) error {
// 实现存储客户的逻辑
return nil
}

为什么这样更好?
遵循接口隔离原则
消费者只需定义它们真正需要的方法
避免依赖不需要的方法
更容易维护
接口变更只影响实际使用该接口的消费者
生产者可以自由添加新方法而不影响现有消费者
更好的解耦
消费者和生产者之间的耦合更松散
更容易进行单元测试和模拟
符合 Go 的设计哲学
接口应该是小而精确的
接口应该由使用者定义
重构建议
删除生产者端的大接口
在各个消费者包中定义所需的小接口
生产者只提供具体实现
例如:

package service
type orderStore interface {// 只定义订单服务需要的方法GetCustomer(id string) (Customer, error)
}
// filepath: service/billing.go
package service
type billingStore interface {// 只定义账单服务需要的方法GetCustomersWithNegativeBalance() ([]Customer, error)
}

这种方式让代码更灵活、更易于维护,也更符合 Go 语言的设计理念。
找到具有 1 个许可证类型的类似代码

package client

import “github.com/teivah/100-go-mistakes/src/02-code-project-organization/6-interface-producer/store”

type customersGetter interface {
GetAllCustomers() ([]store.Customer, error)
}
当前的依赖结构

graph LR
client --> store[store package]
client --> customersGetter[customersGetter interface]

  1. 表面的循环依赖
    当前代码中:
package client
import "github.com/teivah/100-go-mistakes/src/02-code-project-organization/6-interface-producer/store"
type customersGetter interface {GetAllCustomers() ([]store.Customer, error)
}

这里看似存在循环依赖:
client 包引用了 store 包来使用 store.Customer 类型
customersGetter 接口定义在 client 包中
似乎 store 包需要实现 client 包中的接口
2. 实际上不存在循环依赖
实际上这并不是真正的循环依赖,因为:
store 包不需要导入 client 包
store 包不需要显式声明它实现了 customersGetter 接口
Go 的接口是隐式实现的
3. 更好的设计方案
package client
// 1. 在 client 包中定义自己的 Customer 类型
type Customer struct {
// 客户端需要的字段
}
type customersGetter interface {
GetAllCustomers() ([]Customer, error)
}
// 2. 使用适配器模式
type storeAdapter struct {
store store.CustomerStorage
}
func (sa *storeAdapter) GetAllCustomers() ([]Customer, error) {
storeCustomers, err := sa.store.GetAllCustomers()
if err != nil {
return nil, err
}
// 转换 store.Customer 到 client.Customer
return convertCustomers(storeCustomers), nil
}

改进建议
定义自己的类型
每个包应该定义自己需要的类型
避免直接依赖其他包的具体类型
使用适配器
在边界处转换类型
减少包之间的直接依赖
保持接口小巧
只定义真正需要的方法
避免不必要的依赖
依赖注入
使用依赖注入来管理依赖关系
提高代码的可测试性
这种方式可以让代码更加清晰和模块化,同时避免包之间的紧耦合。

client 包可以为其需求定义最精准的抽象。它与接口隔离原则(soild)中的i 概念有关。该原则指出,任何客户端都不应该被破译来他不使用的方法。因此,这种情况下,最好的方法是在生产者端公开具体的实现,并让客户端决定如何使用它以及是否需要抽象。

函数返回签名。
为什么很多情况下返回一个接口被认为是一个糟糕的做法?
如果函数返回接口而不是结构体,将会产生依赖关系。

如果考虑两个包:
client包:包含一个store 接口
store包: 包含store 的实现
在store包中,我们定义了一个实现store 接口的 inmemorystore 结构体,同时创建了一个

原则:
返回结构体而不是接口
尽可能地接收接口。

在大多数情况下,我们不应返回接口,而是应返回具体的实现。否则,由于包的依赖关系,它会使我们的设计更加复杂,并且会限制灵活性,因为所有客户端都必须依赖于相同的抽象。
同样,如果知道(而不是预见到)一个抽象将对客户端有帮助,那么可以考虑返回一个接口,否则不应该强制抽象,这些抽象应该由客户端发现。

eg. 打破规则的例子:
io包检查标准库:
LimitReader

Go 1.18 引入的泛型(Type Parameters)确实改变了某些编程模式,但并未颠覆 Rob Pike 提出的接口设计原则(如“接口应小而专注”)。以下从技术角度详细分析这一变化:


泛型如何减少对 interface{} 和反射的依赖

1. 替代 interface{} 的场景

泛型前(Go 1.17 及更早):
需用 interface{} 实现通用容器或算法,例如一个通用栈:

type Stack struct {data []interface{}
}
func (s *Stack) Push(v interface{}) { s.data = append(s.data, v) }
func (s *Stack) Pop() interface{} { /* ... */ }

问题:

  • 类型不安全(需运行时类型断言)
  • 性能损失(interface{} 涉及动态内存分配)

泛型后(Go 1.18+):
直接通过类型参数约束:

type Stack[T any] struct {data []T
}
func (s *Stack[T]) Push(v T) { s.data = append(s.data, v) }
func (s *Stack[T]) Pop() T { /* ... */ }

优势:

  • 编译时类型安全(无需类型断言)
  • 性能优化(避免 interface{} 的装箱拆箱)

2. 减少反射的使用

泛型前:
需用反射实现通用逻辑,例如一个合并两个 map 的函数:

func MergeMaps(a, b interface{}) interface{} {va := reflect.ValueOf(a)vb := reflect.ValueOf(b)// 反射检查类型、合并键值对...
}

问题:

  • 代码复杂度高
  • 运行时错误风险

泛型后:
通过类型参数直接约束 map 类型:

func MergeMaps[K comparable, V any](a, b map[K]V) map[K]V {merged := make(map[K]V)for k, v := range a { merged[k] = v }for k, v := range b { merged[k] = v }return merged
}

优势:

  • 代码简洁且类型安全
  • 无需反射即可实现通用逻辑

泛型为何未颠覆接口设计原则?

1. 接口的核心作用未变

泛型解决的是数据类型的通用性问题,而接口定义的是行为的抽象。二者是互补关系:

  • 接口:定义“能做什么”(如 io.ReaderRead() 方法)。
  • 泛型:定义“处理什么类型”(如 Stack[T] 中的 T)。

示例:

// 接口定义行为(未依赖泛型)
type Processor interface {Process(data []byte) error
}// 泛型定义数据类型
type Pipeline[T Processor] struct {processors []T
}

接口仍保持小而专注,泛型仅约束 Pipeline 处理的具体类型。


2. 小接口组合的实践仍被推崇

即使使用泛型,Go 社区仍鼓励通过小接口组合实现功能。例如:

// 小接口定义
type Cloner[T any] interface {Clone() T
}// 泛型函数利用接口
func Duplicate[T Cloner[T]](original T) T {return original.Clone()
}

此处 Cloner 接口仅包含一个方法,符合“接口应小”的原则,泛型仅用于约束 T 必须实现该行为。


3. 泛型无法替代接口的多态性

泛型在编译时确定具体类型,而接口在运行时实现动态分发。二者适用于不同场景:

  • 泛型:适用于算法和容器(如排序、链表)。
  • 接口:适用于插件化架构或运行时多态(如不同数据库驱动实现同一接口)。

示例:

// 接口实现运行时多态
type Driver interface {Connect() error
}var drivers = map[string]Driver{"mysql":    &MySQLDriver{},"postgres": &PostgresDriver{},
}// 泛型实现编译时类型安全
func Query[T any](db *DB, sql string) ([]T, error) { /* ... */ }

三、实际场景中的协同作用

1. 标准库的实践

Go 标准库在引入泛型后,依然遵循接口设计原则:

  • slices:泛型函数(如 Sort)操作切片,但依赖元素的 Less 方法(通过接口约束)。
  • maps:泛型函数处理 map,但键仍需满足 comparable 约束(本质是内置接口)。
2. 减少反射的滥用

泛型显著减少了 JSON 解析、ORM 等场景对反射的依赖:

// 泛型替代反射解析 JSON
func ParseJSON[T any](data []byte) (T, error) {var result Tif err := json.Unmarshal(data, &result); err != nil {return zero(T), err}return result, nil
}

四、未完全替代的场景

1. interface{} 的剩余用途

以下场景仍需 interface{}

  • 处理未知类型:如 fmt.Println 的参数。
  • 动态数据模型:如解析任意结构的 JSON(结合 map[string]interface{})。
2. 反射的必要性

反射在以下场景仍不可替代:

  • 结构体标签解析:如 json:"field"
  • 动态调用方法:如根据字符串名称调用函数。

总结

泛型的引入优化了 Go 的类型系统,减少了 interface{} 和反射的滥用,但并未改变接口设计的核心原则:

  • 泛型:解决“数据类型通用性”问题,提升类型安全和性能。
  • 接口:解决“行为抽象”问题,保持代码灵活性和可扩展性。

二者共同推动 Go 向“静态类型安全 + 动态行为抽象”的平衡发展,而非相互替代。开发者应结合场景选择工具:

  • 优先泛型:处理通用算法和容器。
  • 优先接口:定义组件交互协议。
  • 慎用反射:仅在必要时(如框架开发)使用。

相关文章:

【go语言规范】关于接口设计

抽象应该被发现,而不是被创造。为了避免不必要的复杂性,需要时才创建接口,而不是预见到需要它,或者至少可以证明这种抽象是有价值的。 “The bigger the interface, the weaker the abstraction. 不要用接口进行设计,要…...

计算机视觉+Numpy和OpenCV入门

Day 1:Python基础Numpy和OpenCV入门 Python基础 变量与数据类型、函数与类的定义、列表与字典操作文件读写操作(读写图像和数据文件) 练习任务:写一个Python脚本,读取一个图像并保存灰度图像。 import cv2 img cv2.im…...

计算机网络之网络层(网络层的功能,异构网络互联,路由与转发,SDN基本概念,拥塞控制)

计算机网络之网络层 网络层(Network Layer)是计算机网络体系结构中至关重要的一层,它位于数据链路层(Data Link Layer)和传输层(Transport Layer)之间,主要负责数据包从源主机到目的…...

利用雪花算法+Redis 自增 ID,生成订单号

在我们的项目中,我们需要定义一些全局唯一的 ID,比如订单号,支付单号等等。 这些ID有以下几个基本要求: 1、不能重复 2、不可被预测 3、能适应分库分表 为了生成一个这样一个全局的订单号,自定义了一个分布式 ID …...

第35次CCF计算机软件能力认证 python 参考代码

题目列表1. 密码2. 字符串变换3. 补丁应用4. 通讯延迟5. 木板切割题目列表 第35次CCF计算机软件能力认证 1. 密码 n = int(input()) for _ in range(n):s =...

【探商宝】:大数据与AI赋能,助力中小企业精准拓客引

引言:在数据洪流中,如何精准锁定商机? 在竞争激烈的商业环境中,中小企业如何从海量信息中快速筛选出高价值客户?如何避免无效沟通,精准触达目标企业? 探商宝——一款基于大数据与AI技术的企业信…...

npm 私服使用介绍

一、导读 本文主要介绍 npm 私服的使用,至于 npm 私服搭建的过程,可以看本人之前的文章《Docker 部署 verdaccio 搭建 npm 私服》 二、前置条件 npm私服地址:http://xxx.xxx.xxx.xxx:port/ 三、本地 npm 源切换 使用nrm,可以方…...

【Python 打造高效文件分类工具】

【Python】 打造高效文件分类工具 一、代码整体结构二、关键代码解析(一)初始化部分(二)界面创建部分(三)核心功能部分(四)其他辅助功能部分 三、运行与使用四、示图五、作者有话说 …...

水务+AI应用探索(一)| FastGPT+DeepSeek 本地部署

在当下的科技浪潮中,AI 无疑是最炙手可热的焦点之一,其强大的能力催生出了丰富多样的应用场景,广泛渗透到各个行业领域。对于水务行业而言,AI 的潜力同样不可估量。为了深入探究 AI 在水务领域的实际应用成效,切实掌握…...

基于若依开发的工程项目管理系统开源免费,用于工程项目投标、进度及成本管理的OA 办公开源系统,非常出色!

一、简介 今天给大家推荐一个基于 RuoYi-Flowable-Plus 框架二次开发的开源工程项目管理系统,专为工程项目的投标管理、项目进度控制、成本管理以及 OA 办公需求设计。 该项目结合了 Spring Boot、Mybatis、Vue 和 ElementUI 等技术栈,提供了丰富的功能…...

最新Apache Hudi 1.0.1源码编译详细教程以及常见问题处理

1.最新Apache Hudi 1.0.1源码编译 2.Flink、Spark、Hive集成Hudi 1.0.1 3.flink streaming写入hudi 目录 1. 版本介绍 2. 安装maven 2.1. 下载maven 2.2. 设置环境变量 2.3. 添加Maven镜像 3. 编译hudi 3.1. 下载hudi源码 3.2. 修改hudi源码 3.3. 修改hudi-1.0.1/po…...

设计模式-工厂模式

设计模式 - 工厂模式 工厂模式(Factory Pattern)是一种创建型设计模式,它通过定义一个用于创建对象的接口,让子类决定实例化哪一个类,从而使得一个类的实例化延迟到子类。工厂模式通过将对象创建的逻辑抽象化&#xf…...

基于opencv的HOG+角点匹配教程

1. 引言 在计算机视觉任务中,特征匹配是目标识别、图像配准和物体跟踪的重要组成部分。本文介绍如何使用 HOG(Histogram of Oriented Gradients,方向梯度直方图) 和 角点检测(Corner Detection) 进行特征匹…...

《深度学习》——调整学习率和保存使用最优模型

调整学习率 在使用 PyTorch 进行深度学习训练时,调整学习率是一个重要的技巧,合适的学习率调整策略可以帮助模型更好地收敛。 PyTorch 提供了多种调整学习率的方法,下面将详细介绍几种常见的学习率调整策略及实例代码: torch.opt…...

Ubuntu22.04配置cuda/cudnn/pytorch

Ubuntu22.04配置cuda/cudnn/pytorch 安装cuda官网下载.run文件并且安装/etc/profile中配置cuda环境变量 cudnn安装官网找cuda版本对应的cudnn版本下载复制相应文件到系统文件中 安装pytorch官网找cuda对应版本的pytorchpython代码测试pytorch-GPU版本安装情况 安装cuda 官网下…...

通俗理解-L、-rpath和-rpath-link编译链接动态库

一、参考资料 链接选项 rpath 的应用和原理 | BewareMyPower的博客 使用 rpath 和 rpath-link 确保 samba-util 库正确链接-CSDN博客 编译参数-Wl和rpath的理解_-wl,-rpath-CSDN博客 Using LD, the GNU linker - Options Directory Options (Using the GNU Compiler Colle…...

【Golang】GC探秘/写屏障是什么?

之前写了 一篇【Golang】内存管理 ,有了很多的阅读量,那么我就接着分享一下Golang的GC相关的学习。 由于Golang的GC机制一直在持续迭代,本文叙述的主要是Go1.9版本及以后的GC机制,该版本中Golang引入了 混合写屏障大幅度地优化了S…...

Linux(Centos 7.6)命令详解:head

1.命令作用 将每个文件的前10行打印到标准输出(Print the first 10 lines of each FILE to standard output) 2.命令语法 Usage: head [OPTION]... [FILE]... 3.参数详解 OPTION: -c, --bytes[-]K,打印每个文件的前K字节-n, --lines[-],打印前K行而…...

【工具变量】上市公司网络安全治理数据(2007-2023年)

网络安全是国家安全体系的重要组成部分,是确保金融体系稳定运行、维护市场信心的关键。网络安全治理是指通过一系列手段和措施,维护网络安全,保护网络环境的稳定和安全,旨在确保公司网络系统免受未经授权的访问、攻击和破坏&#…...

watermark解释

在 Apache Flink 中,Watermark 是处理事件时间(Event Time)的核心机制,用于解决流处理中因数据乱序或延迟到达而导致的窗口计算不准确问题。理解 Watermark 的关键在于以下几点: 1. 事件时间 vs. 处理时间 事件时间&…...

Transformer 模型介绍(四)——编码器 Encoder 和解码器 Decoder

上篇中讲完了自注意力机制 Self-Attention 和多头注意力机制 Multi-Head Attention,这是 Transformer 核心组成部分之一,在此基础上,进一步展开讲一下编码器-解码器结构(Encoder-Decoder Architecture) Transformer 模…...

Linux安装Minio

1、下载rpm包 2、rpm 安装 rpm -ivh xx.rpm3、通过查看minion状态,查看其配置文件位置 systemctl start minio可以根据情况自定义修改配置文件内容,这里暂时不做修改 4、创建数据文件和日志文件,一般在/usr/local/ 5、编写启动脚本 #!/bi…...

JAVA EE初阶 - 预备知识(三)

一、中间件 中间件是一种处于操作系统和应用程序之间的软件,它能够为分布式应用提供交互、资源共享、数据处理等功能,是现代软件架构中不可或缺的一部分。下面从多个方面为你详细介绍中间件: 定义与作用 定义:中间件是连接两个或…...

百度热力图数据获取,原理,处理及论文应用6

目录 0、数据简介0、示例数据1、百度热力图数据日期如何选择1.1、其他实验数据的时间1.2、看日历1.3、看天气 2、百度热力图几天够研究?部分文章统计3、数据原理3.1.1 ** 这个比较重要,后面还会再次出现。核密度的值怎么理解?**3.1.2 Csv->…...

tcp连接的11种状态及常见问题。

tcp链接整体流程,如下图所示: TCP协议在连接的建立和终止过程中涉及11种状态,这些状态反映了连接的不同阶段。以下是每种状态的详细说明: 1. CLOSED 初始状态,表示没有活动的连接或连接已完全关闭。当应用程序关闭连…...

宝塔面板开始ssl后,使用域名访问不了后台管理

宝塔面板后台开启ssl访问后,用的证书是其他第三方颁发的证书 再使用 域名/xxx 的形式:https://域名:xxx/xxx 访问后台,结果出现如下,不管使用 http 还是 https 的路径访问都进不后台管理 这个时候可以使用 https://ip/xxx 的方式来…...

5.日常英语笔记

sprouted tater 发芽的土豆 fluid 液体,流体 The doctor recommended drinking plenty of fluids 医生建议多喝流质 适应新环境 adapt to the new environment adjust to the new surroundings get used to the new setting accommodate oneself to the new circu…...

利用工业相机及多光谱图像技术助力医疗美容皮肤AI检测方案

随着年轻人对皮肤的管理要求越来越高,“科技护肤”已成为线下医疗美业护肤行业转型升级之趋势。如何利用先进的图像识别技术和AI大数据分析,为医生和消费者提供个性化的皮肤诊断分析和护肤建议,利用工业相机及多光谱成像技术完美实现这一可能…...

qt QOpenGLTexture详解

1. 概述 QOpenGLTexture 是 Qt5 提供的一个类,用于表示和管理 OpenGL 纹理。它封装了 OpenGL 纹理的创建、分配存储、绑定和设置像素数据等操作,简化了 OpenGL 纹理的使用。 2. 重要函数 构造函数: QOpenGLTexture(const QImage &image,…...

【Zookeeper如何实现分布式锁?】

Zookeeper如何实现分布式锁? 一、ZooKeeper分布式锁的实现原理二、ZooKeeper分布式锁的实现流程三、示例代码四、总结一、ZooKeeper分布式锁的实现原理 ZooKeeper是一个开源的分布式协调服务,它提供了一个分布式文件系统的接口,可以用来存储和管理分布式系统的配置信息。 …...

mysql 学习16 视图,存储过程,存储函数,触发器

视图, 存储过程, 存储函数 触发器...

(前端基础)HTML(一)

前提 W3C:World Wide Web Consortium(万维网联盟) Web技术领域最权威和具有影响力的国际中立性技术标准机构 其中标准包括:机构化标准语言(HTML、XML) 表现标准语言(CSS) 行为标准&#xf…...

go设置镜像代理

前言 在 Go 开发中,如果直接从官方源(https://proxy.golang.org)下载依赖包速度较慢,可以通过设置 镜像代理 来加速依赖包的下载。以下是增加 Go 镜像代理的详细方法: 一、设置 Go 镜像代理 1. 使用环境变量设置代理…...

matlab数据处理:创建网络数据

% 创建网格数据 [X, Y] meshgrid(x_data, y_data); 如 x_data [1 2 3 4] X 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 XY_data [X(:), Y(:)]; % 将X和Y合并成一个向量 X(:)表示将矩阵排成一列 XY_data 1 …...

在企业内部私有化部署 DeepSeek 或其他 AI 大模型时,基于一般场景的最低硬件配置建议

1. 中央处理器(CPU) 核心数:至少 4 核心,支持多线程任务。频率:至少 2.5 GHz。CPU 型号:Intel Core i5 或更高(如 i7 或 i9),或 AMD Ryzen 5000 系列以上。多核支持&…...

DeepSeek 助力 Vue 开发:打造丝滑的颜色选择器(Color Picker)

前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 Deep…...

【ArcGIS Pro二次开发】(87):样式_Style的用法

.Stylx类型的文件即为样式库文件&#xff0c;保存了符号样式。 1、根据名字获取当前工程中的style //获取当前工程中的所有style var ProjectStyles Project.Current.GetItems<StyleProjectItem>();//根据名字找出指定的style StyleProjectItem style ProjectStyles.F…...

Jetson Agx Orin平台JP6.0-r36.3版本修复了vi模式下的原始图像损坏(线条伪影)

1.问题描述 这是JP-6.0 GA/ l4t-r36.3.0的一个已知问题 通过vi模式捕获的图像会导致异常线条 参考下面的快照来演示这些线伪影 这个问题只能通过VI模式进行修复,不应该通过LibArgus看到。 此外,这是由于内存问题。 由于upstream已经将属性名称更改为“dma-noncoherent”…...

nlp|微调大语言模型初探索(2),训练自己的聊天机器人

前言 上篇文章记录了具体的微调语言大模型步骤&#xff0c;以及在微调过程中可能遇见的各种报错&#xff0c;美中不足的是只是基于开源数据集的微调&#xff0c;今天来记录一下怎么基于自己的数据集去微调大语言模型&#xff0c;训练自己的智能机器人&#xff01;&#xff01;&…...

如何搭建Wi-Fi CVE漏洞测试环境:详细步骤与设备配置

引言 随着Wi-Fi技术的普及&#xff0c;Wi-Fi网络成为了现代通信的重要组成部分。然而&#xff0c;Wi-Fi网络的安全性始终是一个备受关注的话题。通过漏洞扫描和安全测试&#xff0c;网络管理员可以及早发现并修复Wi-Fi设备中存在的安全隐患。本篇文章将详细介绍如何搭建Wi-Fi …...

【三维重建】FeatureGS:特征值优化的几何精度和伪影减少3DGS的重构

文章&#xff1a;https://arxiv.org/pdf/2501.17655 标题&#xff1a;FeatureGS: Eigenvalue-Feature Optimization in 3D Gaussian Splatting for Geometrically Accurate and Artifact-Reduced Reconstruction 文章目录 摘要一、引言二、相关工作&#xff1a;3D特征三、算法3…...

请解释一下Standford Alpaca格式、sharegpt数据格式-------deepseek问答记录

1 Standford Alpaca格式 json格式数据。Stanford Alpaca 格式是一种用于训练和评估自然语言处理&#xff08;NLP&#xff09;模型的数据格式&#xff0c;特别是在指令跟随任务中。它由斯坦福大学的研究团队开发&#xff0c;旨在帮助模型理解和执行自然语言指令。以下是该格式的…...

WPS的AI助手进化跟踪(灵犀+插件)

Ver V0.0 250216: 如何给WPS安装插件用以支持其他大模型LLM V0.1 250217: WPS的灵犀AI现在是DeepSeek R1(可能是全参数671B) 前言 WPS也有内置的AI&#xff0c;叫灵犀&#xff0c;之前应是自已的LLM模型&#xff0c;只能说是属于“能用&#xff0c;有好过无”&#xff0c;所…...

本地事务简介

本地事务简介 1 事务基本性质 数据库事务的几个特性&#xff1a;原子性(Automicity)、一致性(Consistency)、隔离性或独立性(islation)和持久性(Durability)&#xff0c;简称ACID。 原子性&#xff1a;一系列的操作&#xff0c;其整体不可拆分&#xff0c;要么同时成功&#…...

Python入门全攻略(七)

面向对象-基础 类和对象 类是一个抽象的概念,对象是一个具体的概念。类是对象的模板和蓝图,用来定义对象的属性和方法,对象是类的实例,具有具体的属性和行为。 类的定义 使用class关键字加上类名来定义类,在类的代码块中,我们可以写一些函数,这些函数是对一类对象共…...

SpringBoot 统一功能处理之拦截器、数据返回格式、异常处理

目录 拦截器 一、什么是拦截器 二 拦截器的使用 三 拦截路径配置 四 拦截器的执行流程 统一数据返回格式 统一异常处理 拦截器 一、什么是拦截器 拦截器是Spring框架提供的核心功能之一&#xff0c;主要用来拦截用户的请求&#xff0c;在指定方法前后&#xff0c;根据业务…...

Javascript网页设计案例:通过PDF.js实现一款PDF阅读器,包括预览、页面旋转、页面切换、放大缩小、黑夜模式等功能

前言 目前功能包括&#xff1a; 切换到首页。切换到尾页。上一页。下一页。添加标签。标签管理页面旋转页面随意拖动双击后还原位置 其实按照自己的预期来说&#xff0c;有很多功能还没有开发完&#xff0c;配色也没有全都搞完&#xff0c;先发出来吧&#xff0c;后期有需要…...

js考核第三题

题三&#xff1a;随机点名 要求&#xff1a; 分为上下两个部分&#xff0c;上方为显示区域&#xff0c;下方为控制区域。显示区域显示五十位群成员的学号和姓名&#xff0c;控制区域由开始和结束两个按钮 组成。点击开始按钮&#xff0c;显示区域里的内容开始滚动&#xff0c;…...

新型基于Go语言的恶意软件利用Telegram作为C2通信渠道

研究人员发现了一种新型后门恶意软件&#xff0c;使用Go语言编写&#xff0c;并利用Telegram作为其命令与控制&#xff08;C2&#xff09;通信渠道。尽管该恶意软件似乎仍处于开发阶段&#xff0c;但它已经具备完整的功能&#xff0c;能够执行多种恶意活动。这种创新的C2通信方…...

【Python 语法】Python 正则表达式(regular expressions, regex)

1. 基本语法1.1 字符匹配1.2 元字符1.3 特殊字符1.4 分组和捕获1.5 断言2. 常用函数2.1 `re.match()`2.2 `re.search()`2.3 `re.findall()`2.4 `re.sub()`2.5 `re.split()`3. 进阶用法3.1 捕获组3.2 非捕获组3.3 预查Python 中的**正则表达式(regular expressions, regex)**是…...