空接口(any)
本课属于 Coddy GO 学习旅程的“面向对象编程”单元。第 28 课,共 107 课。
空接口是没有任何方法的接口。由于 Go 中的每种类型至少有 0 个方法,因此每种类型都会自动满足空接口。这使空接口能够保存任何类型的值。
var anything interface{}
anything = 42
anything = "hello"
anything = true
anything = []int{1, 2, 3}从 Go 1.18 开始,引入了关键字 any,作为 interface{} 的别名。它们完全可以互换,但 any 看起来更简洁。
var value any = "Go is awesome"当你需要处理类型未知或各不相同的值时,空接口就很有用。像 fmt.Println 这样的函数会使用它来接受任意类型的参数:
func PrintAnything(v any) {
fmt.Println("Value:", v)
}
func main() {
PrintAnything(100)
PrintAnything("text")
PrintAnything(3.14)
}不过,这也有代价。当一个值存储在空接口中时,你就无法再访问它的具体类型信息。
如果不先提取底层类型,就不能直接调用方法或访问字段。接下来的几课会介绍如何使用类型断言和类型开关,从空接口中获取具体类型。
挑战
简单让我们使用空接口构建一个灵活的存储容器,它可以保存任意类型的值。你将创建一个简单的盒子,展示 any 如何让你在同一个结构体中存储不同类型的值。
你需要将代码分布在两个文件中:
box.go:定义一个Box结构体,其中只有一个类型为any的字段Content。创建一个NewBox构造函数,它接受任意类型的值,并返回一个指向包含该值的 Box 的指针。添加一个Describe方法,返回一个字符串,说明盒子中存储的内容。main.go:从输入中读取不同的值,创建分别包含整数、字符串和布尔值的盒子,然后打印每个盒子的描述,展示同一种 Box 类型如何保存完全不同的值。
输入将按以下格式提供:
- 第 1 行:一个整数值
- 第 2 行:一个字符串值
- 第 3 行:一个布尔值(
true或false)
你的 Describe 方法应返回符合以下格式的字符串:
Box contains: [value]例如,给定 42、hello 和 true,你的输出应为:
Box contains: 42
Box contains: hello
Box contains: true这里的关键在于,你的单个 Box 结构体可以存储整数、字符串或布尔值,这一切都归功于 any 类型可以接受任意类型的值。每个盒子保存的内容都不同,但它们的类型都是 Box。
亲手试试
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
// 读取整数值
line1, _ := reader.ReadString('\n')
intVal, _ := strconv.Atoi(strings.TrimSpace(line1))
// 读取字符串值
line2, _ := reader.ReadString('\n')
strVal := strings.TrimSpace(line2)
// 读取布尔值
line3, _ := reader.ReadString('\n')
boolVal, _ := strconv.ParseBool(strings.TrimSpace(line3))
// TODO: 使用 NewBox 为每个值创建盒子
// TODO: 使用 Describe 方法打印每个盒子的描述
// 使用这些变量以避免编译错误(实现时删除这些代码行)
_ = intVal
_ = strVal
_ = boolVal
// 输出格式示例:
// fmt.Println(box.Describe())
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
自己练习: Go 在线编译器