Go语言没有Java风格的异常处理机制,也不支持子类型继承。Go使用错误值(error)进行错误处理,并通过接口和组合来实现多态。以下是Go语言中处理类似场景的最佳实践:
1. 错误处理(替代Java异常)
package main
import (
"errors"
"fmt"
"io"
)
// 定义错误类型
var (
ErrRemote = errors.New("remote error")
ErrIO = errors.New("io error")
)
// 接口定义
type Processor interface {
Process() error
}
// 结构体1
type Class1 struct{}
func (c *Class1) Process() error {
fmt.Println("m1 in class1")
// 模拟可能发生的错误
return ErrRemote
}
// 结构体2
type Class2 struct{}
func (c *Class2) Process() error {
fmt.Println("m1 in class2")
// 模拟可能发生的错误
return ErrIO
}
func main() {
var obj Processor = &Class1{}
// 错误处理
if err := obj.Process(); err != nil {
switch err {
case ErrRemote:
fmt.Println("remote exception")
case ErrIO:
fmt.Println("io exception")
default:
fmt.Println("unknown error:", err)
}
}
}
2. 使用接口实现多态(替代继承)
package main
import (
"fmt"
)
// 基础接口
type M1er interface {
M1() error
}
// 结构体1实现
type Class1 struct {
name string
}
func (c *Class1) M1() error {
fmt.Printf("m1 in class1: %s\n", c.name)
return nil
}
// 结构体2实现
type Class2 struct {
Class1 // 嵌入结构体实现组合
id int
}
func (c *Class2) M1() error {
fmt.Printf("m1 in class2 - id: %d, name: %s\n", c.id, c.name)
return nil
}
func main() {
// 多态示例
var obj M1er
obj = &Class1{name: "test1"}
obj.M1()
obj = &Class2{
Class1: Class1{name: "test2"},
id: 100,
}
obj.M1()
}
3. 带错误链的复杂示例
package main
import (
"fmt"
"os"
)
// 自定义错误类型
type FileError struct {
Op string
Path string
Err error
}
func (e *FileError) Error() string {
return fmt.Sprintf("%s %s: %v", e.Op, e.Path, e.Err)
}
func (e *FileError) Unwrap() error {
return e.Err
}
// 文件处理器
type FileProcessor struct {
filename string
}
func (fp *FileProcessor) Process() error {
file, err := os.Open(fp.filename)
if err != nil {
return &FileError{
Op: "open",
Path: fp.filename,
Err: err,
}
}
defer file.Close()
// 处理文件内容
fmt.Printf("Processing file: %s\n", fp.filename)
return nil
}
func main() {
processor := &FileProcessor{filename: "test.txt"}
if err := processor.Process(); err != nil {
fmt.Printf("Error occurred: %v\n", err)
// 错误类型断言
if fileErr, ok := err.(*FileError); ok {
fmt.Printf("File operation failed: %s on %s\n",
fileErr.Op, fileErr.Path)
}
}
}
4. 使用recover处理panic(类似Java的catch)
package main
import (
"fmt"
)
func safeFunction() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from panic:", r)
}
}()
// 可能引发panic的代码
panic("something went wrong")
fmt.Println("This line won't be executed")
}
func main() {
safeFunction()
fmt.Println("Program continues after panic recovery")
}
Go语言的错误处理哲学是显式处理错误,而不是通过异常机制。每个可能失败的操作都应该返回错误值,调用者需要检查并处理这些错误。对于继承,Go使用接口和组合来实现多态行为。