前面几章看得轻松愉快,看到最后几章感觉脑子不太够用,学习进度指数级下降。白天总算是把错误处理章的最后一个例子完整打了一遍。
自定义错误
package main
import (
"errors"
"fmt"
"os"
"strings"
)
//类型与常量
const rows, columns = 9, 9
type SudokuError []error
type Grid [rows][columns]int8
//声明错误变量
var (
ErrBounds = errors.New("out of bounds")
ErrDigit = errors.New("invalid digit")
)
//实现接口方法
func (se SudokuError) Error() string {
var s []string
for _, err := range se {
s = append(s, err.Error())
}
return strings.Join(s, ", ")
}
func inBounds(row, column int) bool {
if row < 0 || row >= rows {
return false
}
if column < 0 || column >= columns {
return false
}
return true
}
func validDigit(digit int8) bool {
return digit >= 1 && digit <= 9
}
func (g *Grid) Set(row, column int, digit int8) error {
var errs SudokuError
if !inBounds(row, column) {
errs = append(errs, ErrBounds)
}
if !validDigit(digit) {
errs = append(errs, ErrDigit)
}
if len(errs) > 0 {
return errs
}
g[row][column] = digit
return nil
}
func main() {
var g Grid
err := g.Set(10, 0, 15)
//类型断言
if err != nil {
if errs, ok := err.(SudokuError); ok {
fmt.Printf("%d error(s) occurred:\n", len(errs))
for _, e := range errs {
fmt.Printf("- %v\n", e)
}
}
os.Exit(1)
}
}类型断言
虽然想不出什么好词儿,但就是感觉断言这个词挺中二的。在 Go 里,接口变量可以存储任何实现了它的具体类型的值。但当你拿到一个接口变量时,编译器不知道它里面装的具体是什么类型。如果你想调用这个具体类型独有的方法或字段,就必须先通过类型断言把它“取出来”。
通俗点说,就是数据已经拿到了,但是类型是接口类型,不方便拆分调用,你原来该是什么类型,最好想办法还转为原来的数据类型。

