Golang 06 接口与反射
总篇:33
编辑于 2025/6/23 20:00
截稿于: 2025/6/23 23:00
第十一章
接口
和Java的接口差别不大,Go没有类和继承的概念,接口成了方法的核心。
声明接口
一个接口的方法可以被多个结构体实现,同时结构体必须实现接口内所有方法,否则编译报错。
package interfaces
// Shape 定义了一个接口,包含一个 Area 方法
type Shape interface {
Area() float64
}
// Circle 表示一个圆
type Circle struct {
Radius float64
}
// Rectangle 表示一个矩形
type Rectangle struct {
Width float64
Height float64
}
// Circle 的 Area 方法
func (c Circle) Area() float64 {
return 3.14159 * c.Radius * c.Radius
}
// Rectangle 的 Area 方法
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
package main
import (
"day06/interfaces"
"fmt"
)
func main() {
// 创建一个 Circle 实例
circle := interfaces.Circle{Radius: 5}
// 创建一个 Rectangle 实例
rectangle := interfaces.Rectangle{Width: 4, Height: 6}
// 将 Circle 和 Rectangle 赋值给 Shape 类型的变量
var shape interfaces.Shape
shape = circle
fmt.Println("Circle area:", shape.Area()) // 输出: Circle area: 78.53975
shape = rectangle
fmt.Println("Rectangle area:", shape.Area()) // 输出: Rectangle area: 24
}

嵌套接口
一个接口可以包含一个或多个其他的接口,这相当于直接将这些内嵌接口的方法列举在外层接口中一样。
在File接口内就有应用:
type ReadWrite interface {
Read(b Buffer) bool
Write(b Buffer) bool
}
type Lock interface {
Lock()
Unlock()
}
type File interface {
ReadWrite // 展开有Read,Write方法
Lock // 展开Lock() Unlock() 方法
Close() //File自定义的方法
}
类型断言:检测和转换接口变量的类型
package main
import (
"day06/interfaces"
"fmt"
)
func main() {
//interface1()
interface2()
}
func interface1() {
// 创建一个 Circle 实例
circle := interfaces.Circle{Radius: 5}
// 创建一个 Rectangle 实例
rectangle := interfaces.Rectangle{Width: 4, Height: 6}
// 将 Circle 和 Rectangle 赋值给 Shape 类型的变量
var shape interfaces.Shape
shape = circle
fmt.Println("Circle area:", shape.Area()) // 输出: Circle area: 78.53975
shape = rectangle
fmt.Println("Rectangle area:", shape.Area()) // 输出: Rectangle area: 24
}
func interface2() {
circle := interfaces.Circle{Radius: 5}
circle.Radius = 5
var shape interfaces.Shape
shape = circle
if t, ok := shape.(*interfaces.Circle); ok {
fmt.Println("Circle area:", t.Area())
} else { //circle是字面量初始化,不是指针,所以会走到这里
fmt.Println("Not a circle pointer")
}
}

使用swtich-case 语句:
package main
import (
"day06/interfaces"
"fmt"
)
func main() {
interface2()
}
func interface2() {
circle := interfaces.Circle{Radius: 5}
circle.Radius = 5
var shape interfaces.Shape
shape = circle
switch t := shape.(type) {
case interfaces.Circle:
fmt.Printf("Type Square %T with value %v\n", t, t)
case interfaces.Rectangle:
fmt.Printf("Type Circle %T with value %v\n", t, t)
case nil:
fmt.Printf("nil value: nothing to check?\n")
default:
fmt.Printf("Unexpected type %T\n", t)
}
}
Go 语言规范定义了接口方法集的调用规则:
- 类型 *T 的可调用方法集包含接受者为 *T 或 T 的所有方法集
- 类型 T 的可调用方法集包含接受者为 T 的所有方法
- 类型 T 的可调用方法集不包含接受者为 *T 的方法
即指针优先级最高,感觉就用值接收者就足够了。
以下举例:
package main
import (
"fmt"
"math"
)
// Shape 定义了一个接口,包含一个 Area 方法
type Shape interface {
Area() float64
}
// Circle 表示一个圆
type Circle struct {
Radius float64
}
// Rectangle 表示一个矩形
type Rectangle struct {
Width float64
Height float64
}
// Circle 的 Area 方法(指针接收者)
func (c *Circle) Area() float64 {
return math.Pi * c.Radius * c.Radius
}
// Rectangle 的 Area 方法(值接收者)
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
指针:
func main() {
// 创建一个值类型的 Rectangle 实例
rectangle := Rectangle{Width: 4, Height: 6}
// 将 rectangle 赋值给 Shape 接口
var shape Shape = rectangle
// 调用接口方法
fmt.Println("Rectangle area:", shape.Area()) // 输出: Rectangle area: 24
}
值:
func main() {
// 创建一个值类型的 Rectangle 实例
rectangle := Rectangle{Width: 4, Height: 6}
// 调用值接收者方法
fmt.Println("Rectangle area:", rectangle.Area()) // 输出: Rectangle area: 24
// 不能调用指针接收者方法
// rectangle.SetWidth(10) // 编译错误:cannot call pointer method on rectangle
}
空接口
空接口或者最小接口 不包含任何方法,它对实现不做任何要求,可以被赋予任何值:
type Any interface {}
package main
import (
"day06/interfaces"
"fmt"
)
func main() {
interface3()
}
func interface3() {
var any interfaces.Any
any = 3
fmt.Println(any)
any = "hello"
fmt.Println(any)
cirlce := interfaces.Circle{Radius: 5}
any = cirlce
fmt.Println(any)
}

使用空接口实现仍以类型的切片或数组,感觉很鸡肋:
package main
import (
"day06/interfaces"
"fmt"
)
func main() {
interface4()
}
func interface4() {
// 创建一个包含不同类型值的切片
var mixed []interface{}
mixed = append(mixed, 42) // int
mixed = append(mixed, "hello") // string
mixed = append(mixed, 3.14) // float64
mixed = append(mixed, true) // bool
mixed = append(mixed, []int{1, 2, 3}) // []int
// 遍历切片并打印每个元素
for _, value := range mixed {
fmt.Printf("Type: %T, Value: %v\n", value, value)
}
}

反射包
reflect.TypeOf(x):获取x的类型,reflect.ValueOf(x):获取x的值
package main
import (
"day06/interfaces"
"fmt"
"reflect"
)
func main() {
reflect1()
}
func reflect1() {
var x float64 = 3.4
fmt.Println("type:", reflect.TypeOf(x))
v := reflect.ValueOf(x)
fmt.Println("value:", v)
fmt.Println("type:", v.Type())
fmt.Println("kind:", v.Kind())
fmt.Println("value:", v.Float())
fmt.Println(v.Interface())
fmt.Printf("value is %5.2e\n", v.Interface())
y := v.Interface().(float64)
fmt.Println(y)
}
浙公网安备 33010602011771号