Day10 Go语言深入学习(2)
1.包
2.错误
import ("errors""fmt"
)func main() {err := errors.New("this is an error")fmt.Println(err) // 输出:this is an error
}package mainimport ("fmt"
)type DivideError struct {Dividend intDivisor int
}func (e *DivideError) Error() string {return fmt.Sprintf("cannot divide %d by %d", e.Dividend, e.Divisor)
}func divide(a, b int) (int, error) {if b == 0 {return 0, &DivideError{Dividend: a, Divisor: b}}return a / b, nil
}func main() {_, err := divide(10, 0)if err != nil {fmt.Println(err) // 输出:cannot divide 10 by 0}
}package mainimport ("fmt"
)// 定义一个 DivideError 结构
type DivideError struct {dividee intdivider int
}// 实现 `error` 接口
func (de *DivideError) Error() string {strFormat := `Cannot proceed, the divider is zero.dividee: %ddivider: 0
`return fmt.Sprintf(strFormat, de.dividee)
}// 定义 `int` 类型除法运算的函数
func Divide(varDividee int, varDivider int) (result int, errorMsg string) {if varDivider == 0 {dData := DivideError{dividee: varDividee,divider: varDivider,}errorMsg = dData.Error()return} else {return varDividee / varDivider, ""}}func main() {// 正常情况if result, errorMsg := Divide(100, 10); errorMsg == "" {fmt.Println("100/10 = ", result)}// 当除数为零的时候会返回错误信息if _, errorMsg := Divide(100, 0); errorMsg != "" {fmt.Println("errorMsg is: ", errorMsg)}}
3.Go并发
线程 进程 并发 并行
go f(x,y,z)
ch:=make(chan int , 200)
package mainimport ("fmt"
)func fibonacci(n int, c chan int) {x, y := 0, 1for i := 0; i < n; i++ {c <- xx, y = y, x+y}close(c)
}func main() {c := make(chan int, 10)go fibonacci(cap(c), c)// range 函数遍历每个从通道接收到的数据,因为 c 在发送完 10 个// 数据之后就关闭了通道,所以这里我们 range 函数在接收到 10 个数据// 之后就结束了。如果上面的 c 通道不关闭,那么 range 函数就不// 会结束,从而在接收第 11 个数据的时候就阻塞了。for i := range c {fmt.Println(i)}
}
并发错误
(1)死锁
● 示例:所有 Goroutine 都在等待,但没有任何数据可用。
● 解决:避免无限等待、正确关闭通道。
(2)数据竞争
● 示例:多个 Goroutine 同时访问同一变量。
● 解决:使用 Mutex 或 Channel 同步访问。
问题一:
go sum(s[len(s)/2:], c)x, y := <-c, <-c // 从通道 c 中接收go sayHello() // 启动 Goroutinefor i := 0; i < 5; i++ {fmt.Println("Main")time.Sleep(100 * time.Millisecond)
问题二:
通道在goroutine并发中起到一个什么角色?
问题三:
import ("fmt""sync"
)func worker(id int, wg *sync.WaitGroup) {defer wg.Done() // Goroutine 完成时调用 Done()fmt.Printf("Worker %d started\n", id)fmt.Printf("Worker %d finished\n", id)
}func main() {var wg sync.WaitGroupfor i := 1; i <= 3; i++ {wg.Add(1) // 增加计数器go worker(i, &wg)}wg.Wait() // 等待所有 Goroutine 完成fmt.Println("All workers done")
}