You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go中接收多种struct类型作为函数参数的惯用实现方式是什么

Go语言接收多类型参数的惯用实现方案

方案1:使用泛型(推荐,Go 1.18及以上版本适用)

这是当前最符合Go惯用设计的方案,不需要给结构体额外加冗余方法,直接通过泛型的类型集合约束参数类型即可,示例代码:

import "fmt"

type Thing struct {
  a int
  b int
  c string
  d string
}

type OtherThing struct {
  e int
  f int
  c string
  d string
}

// 泛型约束:仅允许传入Thing或OtherThing类型的参数
func doSomething[T Thing | OtherThing](t T) error {
  fmt.Println(t.d)
  return nil
}

小提示:如果你的Go版本低于1.21,泛型直接访问共名字段可能会报错,此时可以在函数内加一层类型switch判断,或者给两个结构体添加GetD() string方法,将泛型约束改为实现该接口即可。


方案2:标记接口(兼容Go 1.18以下版本,无泛型时使用)

给两个结构体加统一方法的方案并不是“无意义的适配”,这种叫做标记接口(Marker Interface),是Go里很常见的类型约束方式,实现也很简单:

import "fmt"

type Thing struct {
  a int
  b int
  c string
  d string
}

type OtherThing struct {
  e int
  f int
  c string
  d string
}

// 定义标记接口,所有实现了isThing接口的类型都可以传入
type isThing interface {
  implThing()
}

// 给两个结构体分别实现标记方法,方法不需要任何逻辑
func (Thing) implThing() {}
func (OtherThing) implThing() {}

func doSomething(t isThing) error {
  // 用类型断言取对应字段即可
  switch v := t.(type) {
  case Thing:
    fmt.Println(v.d)
  case OtherThing:
    fmt.Println(v.d)
  default:
    return fmt.Errorf("unsupported type: %T", t)
  }
  return nil
}

这种方案的好处是编译期就能做类型校验,不会漏传不符合要求的类型。


方案3:空接口+类型断言(不推荐,仅临时调试用)

如果不想改结构体定义,也可以直接用interface{}作为参数类型,运行时做类型判断:

import "fmt"

func doSomething(t interface{}) error {
  switch v := t.(type) {
  case Thing:
    fmt.Println(v.d)
  case OtherThing:
    fmt.Println(v.d)
  default:
    return fmt.Errorf("unsupported type: %T", t)
  }
  return nil
}

这种方案的缺点是编译期无法校验参数类型,传错类型只能运行时报错,可维护性差,仅适合临时快速实现的场景。


方案选择建议

  • 如果你用的是Go 1.18及以上版本,优先选泛型方案,代码最简洁也最符合现代Go的设计习惯
  • 如果需要兼容老版本Go,优先选标记接口方案,编译期类型安全有保障
  • 空接口方案仅作为临时备选,不建议在生产代码中长期使用

内容的提问来源于stack exchange,提问作者apr_1985

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 16:54:04