13.1 错误

Go 使用返回值表示错误。

定义错误

err := errors.New("math - square root of negative number")

格式化错误

fmt.Errorf("math: square root of negative number %g", f)
}

13.2 异常

panic 是运行时预料之外的异常。

定义异常

	panic("A severe error occurred: stopping the program!")

13.3 恢复

func protect(g func()) {
	defer func() {
		log.Println("done")
		// Println executes normally even if there is a panic
		if err := recover(); err != nil {
			log.Printf("run time panic: %v", err)
		}
	}()
	log.Println("start")
	g() //   possible runtime-error
}

在 defer 修饰的函数中可以捕获 recover,以便进行日志记录和恢复等操作。

13.4 自定义错误

type ParseError struct {
    Index int      // The index into the space-separated list of words.
    Word  string   // The word that generated the parse error.
    Err error // The raw error that precipitated this error, if any.
}

13.6 执行外部命令

// exec.go
package main
import (
	"fmt"
    "os/exec"
	"os"
)

func main() {
// 1) os.StartProcess //
/*********************/
/* Linux: */
env := os.Environ()
procAttr := &os.ProcAttr{
			Env: env,
			Files: []*os.File{
				os.Stdin,
				os.Stdout,
				os.Stderr,
			},
		}
// 1st example: list files
pid, err := os.StartProcess("/bin/ls", []string{"ls", "-l"}, procAttr)  
if err != nil {
		fmt.Printf("Error %v starting process!", err)  //
		os.Exit(1)
}
fmt.Printf("The process id is %v", pid)

13.7 测试

假设我们写了一个二分查找:

// mid_search.go

package main

import "fmt"

func Search(arr []int, val int) (index int) {
	var lo = 0
	var hi = len(arr) - 1
	for lo <= hi {
		var mid = lo + (hi-lo)>>1
		if arr[mid] == val {
			return mid
		}
		if val <= arr[mid] {
			hi = mid - 1
		} else {
			lo = mid + 1
		}
	}
	return -1
}

func main() {
	var arr = []int{1, 2, 3, 10, 20, 40, 128, 324, 888, 1024}
	fmt.Println(Search(arr, 1))
}

创建文件 mid_search_test.go

// mid_search_test.go

package main

import "testing"

func TestSearch(t *testing.T) {
	if ans := Search([]int{}, 1); ans != -1 {
		t.Errorf("wrong, got %v", ans)
	}
	if ans := Search([]int{}, -1); ans != -1 {
		t.Errorf("wrong, got %v", ans)
	}
	if ans := Search([]int{1, 2, 3, 4}, 1); ans != 0 {
		t.Errorf("wrong, got %v", ans)
	}
	if ans := Search([]int{1, 2, 3, 4}, 4); ans != 3 {
		t.Errorf("wrong, got %v", ans)
	}
	if ans := Search([]int{1, 2, 3, 4}, 5); ans != -1 {
		t.Errorf("wrong, got %v", ans)
	}
	if ans := Search([]int{-10, 0, 2, 3}, -10); ans != 0 {
		t.Errorf("wrong, got %v", ans)
	}
	if ans := Search([]int{-10, 0, 2, 3}, 10); ans != -1 {
		t.Errorf("wrong, got %v", ans)
	}
	if ans := Search([]int{-10, 0, 2, 3}, 0); ans != 1 {
		t.Errorf("wrong, got %v", ans)
	}
}

两个文件放到 test_example 目录(自建),并在此目录下执行:

go mod init example.com/test_example

再执行:

go test

即可启动测试