接口是Go语言中实现多态的核心机制。接口定义了一组方法签名,任何实现了这些方法的类型都自动实现了该接口。
package main
import "fmt"
// 定义接口
type Speaker interface {
Speak() string
}
// Dog类型实现Speaker接口
type Dog struct {
Name string
}
func (d Dog) Speak() string {
return "Woof! I'm " + d.Name
}
// Cat类型实现Speaker接口
type Cat struct {
Name string
}
func (c Cat) Speak() string {
return "Meow! I'm " + c.Name
}
func main() {
var s Speaker
s = Dog{Name: "Buddy"}
fmt.Println(s.Speak()) // Woof! I'm Buddy
s = Cat{Name: "Whiskers"}
fmt.Println(s.Speak()) // Meow! I'm Whiskers
}
Go语言的接口实现是隐式的,不需要显式声明。只要类型实现了接口的所有方法,就自动实现了该接口。
type Writer interface {
Write([]byte) (int, error)
}
type FileWriter struct {
filename string
}
// FileWriter自动实现了Writer接口
func (fw FileWriter) Write(data []byte) (int, error) {
fmt.Printf("写入文件 %s: %s\n", fw.filename, string(data))
return len(data), nil
}
func main() {
var w Writer = FileWriter{filename: "test.txt"}
w.Write([]byte("Hello, World!"))
}
空接口interface{}不包含任何方法,因此所有类型都实现了空接口。空接口可以存储任意类型的值。
func main() {
var i interface{}
i = 42
fmt.Println(i) // 42
i = "hello"
fmt.Println(i) // hello
i = []int{1, 2, 3}
fmt.Println(i) // [1 2 3]
// 空接口切片
slice := []interface{}{1, "hello", 3.14, true}
for _, v := range slice {
fmt.Printf("%v (%T)\n", v, v)
}
}
类型断言用于从接口值中提取底层具体类型的值。
func main() {
var i interface{} = "hello"
// 类型断言
s := i.(string)
fmt.Println(s) // hello
// 安全的类型断言
s, ok := i.(string)
if ok {
fmt.Println("字符串:", s)
}
// 断言失败
n, ok := i.(int)
if !ok {
fmt.Println("不是整数")
}
}
func describe(i interface{}) {
switch v := i.(type) {
case int:
fmt.Printf("整数: %d\n", v)
case string:
fmt.Printf("字符串: %s\n", v)
case bool:
fmt.Printf("布尔: %t\n", v)
case float64:
fmt.Printf("浮点数: %.2f\n", v)
default:
fmt.Printf("未知类型: %T\n", v)
}
}
func main() {
describe(42)
describe("hello")
describe(true)
describe(3.14)
describe([]int{1, 2, 3})
}
接口可以通过嵌入其他接口来组合。
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
type Closer interface {
Close() error
}
// 组合接口
type ReadWriter interface {
Reader
Writer
}
type ReadWriteCloser interface {
Reader
Writer
Closer
}
type File struct {
name string
}
func (f *File) Read(p []byte) (int, error) {
fmt.Println("读取文件:", f.name)
return 0, nil
}
func (f *File) Write(p []byte) (int, error) {
fmt.Println("写入文件:", f.name)
return len(p), nil
}
func (f *File) Close() error {
fmt.Println("关闭文件:", f.name)
return nil
}
func main() {
var rwc ReadWriteCloser = &File{name: "test.txt"}
rwc.Read(nil)
rwc.Write([]byte("data"))
rwc.Close()
}
接口值由两部分组成:具体类型和具体值。
type Speaker interface {
Speak() string
}
type Dog struct {
Name string
}
func (d Dog) Speak() string {
return "Woof!"
}
func main() {
var s Speaker
fmt.Printf("(%v, %T)\n", s, s) // (, )
s = Dog{Name: "Buddy"}
fmt.Printf("(%v, %T)\n", s, s) // ({Buddy}, main.Dog)
}
type Speaker interface {
Speak() string
}
type Dog struct {
Name string
}
func (d *Dog) Speak() string {
if d == nil {
return "nil dog"
}
return "Woof! I'm " + d.Name
}
func main() {
var s Speaker
fmt.Println(s == nil) // true
var d *Dog
s = d
fmt.Println(s == nil) // false (接口不为nil,但底层值为nil)
fmt.Println(s.Speak()) // nil dog
}
package main
import (
"fmt"
"io"
"strings"
)
func main() {
// strings.Reader实现了io.Reader接口
r := strings.NewReader("Hello, Go!")
buf := make([]byte, 8)
for {
n, err := r.Read(buf)
fmt.Printf("读取 %d 字节: %s\n", n, buf[:n])
if err == io.EOF {
break
}
}
}
type Person struct {
Name string
Age int
}
// 实现fmt.Stringer接口
func (p Person) String() string {
return fmt.Sprintf("%s (%d岁)", p.Name, p.Age)
}
func main() {
p := Person{Name: "Alice", Age: 25}
fmt.Println(p) // Alice (25岁)
}
type error interface {
Error() string
}
// 自定义错误类型
type MyError struct {
Code int
Msg string
}
func (e *MyError) Error() string {
return fmt.Sprintf("错误 %d: %s", e.Code, e.Msg)
}
func doSomething() error {
return &MyError{Code: 404, Msg: "未找到资源"}
}
func main() {
if err := doSomething(); err != nil {
fmt.Println(err) // 错误 404: 未找到资源
}
}
// 好的设计:接受接口
func ProcessData(r io.Reader) error {
// 处理数据
return nil
}
// 不好的设计:接受具体类型
func ProcessFile(f *os.File) error {
// 处理文件
return nil
}
// 好的设计:小而专注的接口
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
// 不好的设计:大而全的接口
type FileOperations interface {
Read(p []byte) (n int, err error)
Write(p []byte) (n int, err error)
Close() error
Seek(offset int64, whence int) (int64, error)
// ... 更多方法
}
package main
import (
"fmt"
"math"
)
type Shape interface {
Area() float64
Perimeter() float64
}
type Rectangle struct {
Width, Height float64
}
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
func (r Rectangle) Perimeter() float64 {
return 2 * (r.Width + r.Height)
}
type Circle struct {
Radius float64
}
func (c Circle) Area() float64 {
return math.Pi * c.Radius * c.Radius
}
func (c Circle) Perimeter() float64 {
return 2 * math.Pi * c.Radius
}
func printShapeInfo(s Shape) {
fmt.Printf("面积: %.2f, 周长: %.2f\n", s.Area(), s.Perimeter())
}
func main() {
rect := Rectangle{Width: 10, Height: 5}
circle := Circle{Radius: 5}
printShapeInfo(rect)
printShapeInfo(circle)
}
package main
import "fmt"
type Database interface {
Connect() error
Query(sql string) ([]map[string]interface{}, error)
Close() error
}
type MySQL struct {
host string
port int
}
func (m *MySQL) Connect() error {
fmt.Printf("连接到MySQL %s:%d\n", m.host, m.port)
return nil
}
func (m *MySQL) Query(sql string) ([]map[string]interface{}, error) {
fmt.Println("执行MySQL查询:", sql)
return nil, nil
}
func (m *MySQL) Close() error {
fmt.Println("关闭MySQL连接")
return nil
}
type PostgreSQL struct {
host string
port int
}
func (p *PostgreSQL) Connect() error {
fmt.Printf("连接到PostgreSQL %s:%d\n", p.host, p.port)
return nil
}
func (p *PostgreSQL) Query(sql string) ([]map[string]interface{}, error) {
fmt.Println("执行PostgreSQL查询:", sql)
return nil, nil
}
func (p *PostgreSQL) Close() error {
fmt.Println("关闭PostgreSQL连接")
return nil
}
func executeQuery(db Database, sql string) {
db.Connect()
db.Query(sql)
db.Close()
}
func main() {
mysql := &MySQL{host: "localhost", port: 3306}
postgres := &PostgreSQL{host: "localhost", port: 5432}
executeQuery(mysql, "SELECT * FROM users")
executeQuery(postgres, "SELECT * FROM users")
}
package main
import (
"fmt"
"sort"
)
type Person struct {
Name string
Age int
}
type ByAge []Person
func (a ByAge) Len() int { return len(a) }
func (a ByAge) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }
func main() {
people := []Person{
{"Alice", 25},
{"Bob", 20},
{"Charlie", 30},
}
sort.Sort(ByAge(people))
fmt.Println(people)
}