D
AI
学习工作台
8 周后端冲刺2026-05-222 分钟阅读

Go struct 与 interface

组合优于继承、隐式接口实现、类型断言

8周冲刺week2Gostructinterface记笔记标记疑惑

struct:数据与行为组织

type User struct {
    ID   int
    Name string
}

func (u *User) Rename(name string) { u.Name = name }

值接收者 vs 指针接收者:需修改 receiver 或 struct 较大用指针;小 struct 值拷贝可接受。接口集合需一致:混用会导致同一类型两种 method set。

嵌入与组合

type Admin struct {
    User
    Role string
}

a := Admin{User: User{ID: 1}, Role: "ops"} a.Rename("alice") // 提升调用

面试对比 Java 继承:Go 无子类 override 关键字,通过小接口 + 组合实现多态。

interface 哲学

「接受 interface,返回 struct」。接口应 小而精(io.Reader、io.Writer)。

type Stringer interface {
    String() string
}

func printAll(items []Stringer) { for _, it := range items { fmt.Println(it.String()) } }

空接口 interface{} / any:任意类型;Go 1.18+ 泛型减少滥用 any。

动态分派

var w io.Writer = os.Stdout
w.Write([]byte("hi"))

接口 nil 陷阱:接口值为 nil 需 type 与 data 均为 nil;var p *os.File = nil; var w io.Writer = p 则 w != nil。

类型断言与 switch

func describe(i interface{}) {
    switch v := i.(type) {
    case int:
        fmt.Println("int", v)
    case string:
        fmt.Println("string", v)
    default:
        fmt.Println("unknown")
    }
}

errors.As / errors.Is(Week 3 week03-go-error-testing)基于类型断言链。

与后端设计

  • Repository 接口 + MySQL/Redis 实现,便于测试 mock。
  • Handler 依赖 interface 而非具体 DB,符合依赖倒置。

常见面试题

  • 值类型赋给 interface 是否分配?小值可能 inline,大值堆分配(escape)。
  • 比较 interface:动态类型与动态值均相等才 true。
  • method set 表格:T 与 *T 对接口的方法集差异。
  • 练习

    定义 Storage 接口(Get/Set),实现 memory 与 map 两种 backend;写 table-driven test。下一篇 week02-go-goroutine-channel 进入并发。

    实战巩固与面试表达

    本篇属于 8 周冲刺 week02-go-struct-interface 主题。复习时先闭卷回答 frontmatter 中三张 flashcard,再展开口述两个「为什么」:为什么这种方案能 work、边界失败时如何降级。与相邻章节对照:算法篇强调复杂度与模板,Go 篇强调工程默认写法,中间件篇强调线上故障案例。

    动手与自检清单

    用 25 分钟限时做 1 道相关练习题或画出一张架构/数据结构示意图;用 5 分钟写 STAR 片段说明你在项目里是否用过类似技术。记录 3 个面试追问及你的标准答法,存入 /zh/notebook/master-plan 笔记。若某点不熟,回到对应 /chapters 交互 Lab 重新走一遍流程,比死记卡片更有效。

    易错点提醒

    避免只背名词不会画图;避免只说优点不谈 trade-off(性能、一致性、运维成本至少提一项);避免把学习 Demo 说成百万 QPS 生产。回答时使用「场景 → 方案 → 结果 → 反思」四段式,体现工程成熟度。

    补充要点

    接口 nil 判断是经典坑:typed nil 指针赋给 interface 不为 nil。method set 决定 T 还是 *T 实现接口。测试时用 fake 实现接口,避免 import 循环。泛型 Go 1.18+ 可减少 any 断言,但面试仍常考 interface 语义。

    知识卡片

    问题

    Go 如何实现「继承」?

    点击翻转查看答案

    答案

    用 struct 嵌入(embedding):内嵌字段的方法被提升;是组合不是类继承,无 virtual 表多态开销。

    问题

    interface 何时被 satisfied?

    点击翻转查看答案

    答案

    类型实现接口全部方法即满足,无需显式声明;接口值 = (type, data) 元组。

    问题

    类型断言失败如何处理?

    点击翻转查看答案

    答案

    v, ok := x.(T):ok 为 false 则 v 为零值;或 switch x.(type) 做分支;盲目断言失败会 panic。