如何实现通用接口?

2023-12-12

我刚刚看到 Go 在其最新版本中合并了泛型,我正在尝试创建一个小项目来了解它是如何工作的。除了现在通用的非常简单的功能之外,我似乎不知道它是如何工作的。我希望能够做这样的事情:

type Dao[RT any] interface {
    FindOne(id string) *RT
}

type MyDao struct {
}

type ReturnType struct {
    id int
}

func (m *MyDao) FindOne(id string) *ReturnType {
    panic("implement me")
}

// how should this look like?

func NewMyDao() *Dao[ReturnType] {
    return &MyDao[ReturnType]{}
}

这可能吗?我似乎没有以这种方式实现接口,并且我已经尝试了许多相同的组合。

有没有办法实现通用接口?如果没有,只能选择返回interface{} type?


类型实际上并不实现通用接口,它们实现实例化的通用接口。没有实例化就不能使用泛型类型(包括接口)。从那里开始,它就像前泛型 Go 一样,包括带有指针接收器的方法之间的差异。

因此,考虑使用具体类型重写使用类型参数的方法会是什么样子会很有帮助。

让我们考虑一个通用接口和某种类型:

type Getter[T any] interface {
    Get() T
}

type MyStruct struct {
    Val string
}

有几种可能的情况

具有具体类型参数的接口

实例化为Getter[string],通过带有方法的类型实现Get() string

// implements Getter[string]
func (m MyStruct) Get() string {
   return m.Val
}

// ok
func foo() Getter[string] {
    return MyStruct{}
}

以类型参数作为类型参数的接口

具有类型参数的函数可以使用它们来实例化泛型类型,例如Getter[T]。实施者必须完全具备Get() T方法。为了使其有效,它们也是通用的并使用相同的类型参数进行实例化:

所以即使这样也无法编译T is string

// Getter[T] literally needs implementors with `Get() T` method
func bar[T any]() Getter[T] {
    return MyStruct{} // doesn't compile, even if T is string
}

Making MyStruct也可以参数化工作:

type MyStruct[T any] struct {
    Val T
}

func (m MyStruct[T]) Get() T {
    return m.Val
}

func bar[T any]() Getter[T] {
    return MyStruct[T]{} // ok
}

具有通用实现者的具体接口

让我们把前面的情况颠倒一下。我们保持参数化MyStruct[T any]但现在接口没有参数化:

type Getter interface {
    Get() string
}

在这种情况下,MyStruct实施Getter仅当使用必要的具体类型实例化它时:

// Getter requires method `Get() string`
func baz() Getter {
    return MyStruct[string]{} // instantiate with string, ok
    // return MyStruct[int]{} // instantiate with something else, doesn't compile
}

指针接收器

这遵循与上面相同的规则,但需要像往常一样实例化指针类型:

// pointer receiver, implements Getter[string]
func (m *MyStruct) Get() string {
   return m.Val
}

func foo() Getter[string] {
    return &MyStruct{} // ok
    // return MyStruct{} // doesn't implement
}

如果MyStruct是通用的。

// parametrized pointer receiver
func (m *MyStruct[T]) Get() T {
   return m.Val
}

func foo() Getter[string] {
    return &MyStruct[string]{} // ok
}

因此,在您的情况下,用具体类型替换类型参数的心理练习给出了Dao[ReturnType]有方法FindOne(id string) *ReturnType。实现该方法的类型是*MyDao(指针接收器),因此:

func NewMyDao() Dao[ReturnType] {
    return &MyDao{}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何实现通用接口? 的相关文章

  • 如何不在类中实现接口的功能?

    面试时面试官问了我以下问题 但我不知道这个问题的答案是什么 请帮忙 如果我不想 我必须做什么 在我的类中实现一个函数 在接口中声明为 由我班实施 Edited 我正在使用 NET 和 C 如果有人可以提供 C 示例代码示例 那就太好了 Th
  • 为什么 C# 接口名称前面加上“I”

    这种命名约定背后的基本原理是什么 我没有看到任何好处 额外的前缀只会污染 API 我的想法与康拉德一致response https stackoverflow com a 222502 9898与此相关的question https sta
  • 是否可以使用 go:generate 重定向 stdin/stdout

    我有一个充当管道的工具 它从标准输入读取数据并将源代码写入标准输出 是否可以设置输入 输出重定向并将此类工具与 go generate 一起使用 就像是 go generate tool lt file txt gt file go 我想出
  • 为什么 Go 中的函数不能命名为“init”?

    所以 今天在编码时我发现创建一个名为init产生错误method init not found 但是当我将其重命名为startup一切都很好 init 这个词是为 Go 中的某些内部操作而保留的 还是我在这里遗漏了一些东西 是的 该功能in
  • 与 Reflect.StructTag.Get 不兼容

    我当时在 Google Cloud 中工作 一切都很好 但是当我在 PC 中克隆所有项目时 每个 JSON 结构中都有此消息 结构体字段标签bson edad json edad omitempty 与reflect StructTag G
  • ArrayList 有什么问题?

    最近我问了一个关于 SO 的问题 其中提到了可能使用 c ArrayList 来解决问题 有人评论说使用数组列表不好 我想了解更多有关此的信息 我以前从未听说过关于数组列表的这种说法 有人可以带我了解使用数组列表可能出现的性能问题吗 C n
  • 使用 StructScan 将 postgresql 数组获取到结构中

    测试数据 CREATE TABLE test id int data text INSERT INTO test id data VALUES 1 a b c 去代码吧 第一个 一个运行良好的 func main db sqlx Open
  • 相互递归泛型枚举

    通用递归enum 我可以轻松地用 Swift 表达一个通用的递归枚举 indirect enum Tree
  • 在C#中定义具有不同参数的接口方法

    interface parentInterface public String methodA define parameters name and dataType and public class childA parentInterf
  • Go 算术中处理浮点数精度?

    我对 Go 中精确减去 2 个浮点数的方法感兴趣 我尝试过使用math big图书馆 但我无法得到准确的结果 我用过big js https github com MikeMcl big jsJavascript 库解决了这个问题 Go 算
  • 返回“IList”与“ICollection”与“Collection”

    我对应该从公共 API 方法和属性返回哪种集合类型感到困惑 我想到的收藏是IList ICollection and Collection 返回这些类型中的一种总是优于其他类型 还是取决于具体情况 ICollection
  • 如何避免 Google App Engine 标准环境中 Gorilla 会话的内存泄漏?

    我正在使用 Gorilla 在 Google App Engine 上启用会话变量 到目前为止 我只导入了 github com gorilla sessions 但 Gorilla 的页面显示 如果您不使用 gorilla mux 则需要
  • 如何将 json 字符串编组到 bson 文档以写入 MongoDB?

    我正在寻找的东西相当于文档 parse https api mongodb com java 3 2 org bson Document html parse java lang String 在golang中 这允许我直接从json创建b
  • C# 中的接口属性复制

    我已经使用 C 多年了 但刚刚遇到了这个困扰我的问题 我真的不知道如何提出这个问题 所以 举个例子 public interface IAddress string Address1 get set string Address2 get
  • 如何最大限度地减少 Go 中的垃圾收集?

    有时您可能想避免 最小化垃圾收集器 所以我想确定如何做到这一点 我认为下一个是正确的 在函数的开头声明变量 使用数组代替切片 还有吗 为了最大限度地减少 Go 中的垃圾收集 您必须最大限度地减少堆分配 为了最大限度地减少堆分配 您必须了解分
  • 如何退出执行延迟调用的 go 程序?

    我需要使用defer释放手动创建的分配C图书馆 但我还需要os Exit在某个时刻具有非 0 状态 棘手的部分是os Exit跳过任何延迟指令 package main import fmt import os func main defe
  • golang 将 big.Float 转换为 big.Int

    将big Float转换为big Int 我在下面编写代码 但它溢出了uint64 那么将big Float转换为big Int的正确方法是什么 package main import fmt import math big func Fl
  • 在 Go 中传递任意函数作为参数

    我正在尝试扩展我对 Go 函数指针的了解 并且我有一个问题 在 Go 中将函数作为参数传递可以做什么 不可以做什么 假设我想写一个decorator 可以包装任何现有函数的函数 为简单起见 我们将其限制为仅接受一个参数并仅返回一个值的函数
  • 托管 C++ 中的泛型泛型

    我想创建一个List of 键值对位于托管 C 项目中 这是我正在使用的语法 List
  • 如何在Go包之间共享测试接口?

    Go 不会在不同包的测试文件之间共享代码 因此测试接口的定义不会自动重用 在实践中我们如何解决这个问题 使用示例testing quick foo foo go package foo type Thing int const X Thin

随机推荐

  • 多个文件上传[重复]

    这个问题在这里已经有答案了 如何在任何位置上传多个文件 我的问题是 我正在选择多个文件 但是当我单击上传按钮时 仅上传最后一个文件并重命名名称 并且重命名名称是所有文件名附加逗号 如下所示 file1 file2 flie3 这是代码 Fi
  • Swift 动态库是否向后兼容较旧的 Swift 版本项目

    我开始从头开始开发 SDK 我不太确定应该用 Swift 还是 Objective C 来编写它 我觉得 Swift 在很多方面都比 Objective C 更好 但我的主要问题是 Swift 动态库是否支持旧版本的 Swift 假设我在
  • jQuery Datatables 大数据集未捕获类型错误:无法读取未定义的属性“mData”

    因此 我在使用 php 从数据库迭代的一大组行上收到控制台错误 我正在用 metronic 主题初始化它 正如你所看到的 我有我的头部和身体 我怀疑这个问题可能与输出的大小有关 可能需要使用另一种方法 任何指导表示赞赏 table clas
  • PyQt 从用户处获取日期

    我在 Qt Designer 中使用按钮和 QDateEdit 构建了简单的小部件 用户将日期输入到 QDateEdit 中 然后当他按下按钮时 日期将被保存到变量中 我该怎么做 你可以简单地做到这一点 var name self date
  • 获取 Android Context 的各种方法有什么区别?

    在我见过的各种 Android 代码中 public class MyActivity extends Activity public void method mContext this since Activity extends Con
  • Android ListView 设置要显示的项目数

    如何设置列表中显示的项目数而不滚动 示例 我有一个包含 10 项的列表 我希望只显示 3 个项目 并且我必须滚动才能看到其余的项目 我认为列表视图中显示的项目数量取决于列表可用的大小 我会尝试限制列表大小的布局 如此详细的布局可能不太容易实
  • Play-Framework 2.4:使用 Spring 依赖注入与 Play-Framework 代替 Guice

    我在用Spring Depedency注射代替Play Framework Guice依赖注入 由于你的要求 我们需要使用大部分Spring Modules在我们的应用程序中 例如Spring Data Mongodb但问题是 我们的依赖项
  • Spark Read Json:如何读取整数和结构之间交替的字段

    尝试将多个 json 文件读入数据帧 两个文件都有一个 Value 节点 但该节点的类型在整数和结构之间交替 File 1 Value 123 File 2 Value Value On ValueType State IsSystemVa
  • WKWebView中是否可以关闭位置权限?

    我想知道是否可以阻止WKWebView显示位置权限提示 website com 想要使用您当前的位置 我相信它正在显示 因为该网站包含谷歌地图 我对在其位置预加载位置不感兴趣 就像其他问题中所示 我只是不想在 WKWebView 中使用位置
  • 如何在shell脚本中添加进度条?

    在 bash 或 NIX 中的任何其他 shell 中编写脚本时 如果运行的命令需要花费几秒钟的时间 则需要进度条 例如 复制大文件 打开大 tar 文件 您建议使用哪些方法向 shell 脚本添加进度条 您可以通过覆盖一行来实现这一点 使
  • 更好地突出显示当前编辑组

    VSCode 是否提供了突出显示当前内容的方法编辑组 或选项卡 in focus 例如 突出显示一个边界框在焦点组周围用单独的颜色 如下图所示 突出显示当前选项卡在焦点组中 要修改活动选项卡 请参阅https code visualstud
  • 在 React-Native 中使用 AsyncStorage 更新状态的正确方法是什么?

    我正在尝试向服务器发出 GET 请求以检索 JSON 形式的产品列表 然后我想将数据放入 AsyncStorage 中 以便我可以在视图中显示产品 这样做的正确方法是什么 我研究过的内容 on https facebook github i
  • 将Access数据库分为前端和后端

    好的 我分割了我的访问数据库 现在我有了一个后端 如果我在 db be mdb 中启动了一个全新的表 一个全新的查询和一个用于不同目的的品牌表单 当我将其保存在后端时 它会出现在连接 前端 数据库中 还是必须这样做导入它吗 如果我确实必须导
  • “捕获所有其他”Firebase 数据库规则

    也许我从 SQL 的角度过多地解决了这个问题 但我在理解如何正确限制应该允许哪些子节点填充节点方面遇到了困难 假设我想记录任意名称的产品 每个产品必须包含一个price 但不允许有其他任何事情 我天真的方法是添加一个 validate要求
  • 排除 Elasticsearch 查询中的字段

    具有以下映射 curl XPUT localhost 9200 testidx pretty true d mappings items dynamic strict properties title type string body ty
  • 从内容页面获取并投射 Masterpage UserControl 以访问特定的 UC 属性

    我有一个引用 2 个用户控件的 MasterPage MyBoxx Master 我的用户控件 标题 除其他外还包含一个搜索框 我想在访问某些页面时隐藏此搜索框 因此 我向用户控件添加了一个布尔属性 并在渲染用户控件时使用此属性来确定
  • 从 GCS 提供具有访问限制的静态页面

    我正在谷歌云存储上提供静态页面 只要它是公开的 它就可以很好地工作 现在我设置了 acl 以便只有一组用户可以读取存储 未经身份验证的用户将被重定向到 google 身份验证 现在的问题是 网站的静态内容 例如 javascript 和 c
  • PHP 中两个日期之间的完整天数?

    我将日期存储在 MySQL 表中 格式为 yyyy mm dd 或典型的 MySQL 日期 格式 我怎样才能知道距离那时还剩多少天 例如 如果我有 2011 03 05 它会说 17 More Days In PHP days strtot
  • 如何在 Chart.JS 中显示饼图的数据子集,同时在悬停时仍显示超集?

    我有一个饼图 当鼠标悬停在一块饼上时 它看起来像这样 除了想要传奇在右边而不是在上面 我对此相当满意 但我只想在饼图中 始终 显示百分比值 并且仍然有
  • 如何实现通用接口?

    我刚刚看到 Go 在其最新版本中合并了泛型 我正在尝试创建一个小项目来了解它是如何工作的 除了现在通用的非常简单的功能之外 我似乎不知道它是如何工作的 我希望能够做这样的事情 type Dao RT any interface FindOn