泛型
方法中不能使用泛型
service/history/history.go:43:44: syntax error: method must have no type parameters
时间
格式化打印毫秒
time.Now().Format("2006-01-02 15:04:05.000")
转义
fmt.Sprintf 输出%
`fmt.Sprintf` 使用 `%%` 来输出 `%` 符号
struct
不能直接修改struct的map类型字段
错误
正确修改struct的map字段key,而不是直接修改map
协程中的异常处理
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true, // 忽略证书有效性验证,只为获取证书信息
},
},
}
for _, domain := range domainName {
wg.Add(1)
go func(domain string) {
defer wg.Done()
resp, err := client.Get("https://" + domain)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
defer resp.Body.Close()
// 获取服务器的 TLS 信息
connectionState := resp.TLS
if connectionState == nil {
fmt.Println("No certificates found")
} else {
// 获取第一个证书
cert = connectionState.PeerCertificates[0]
}
fmt.Printf("%v 证书过期时间: %v\n", domain, cert.NotAfter)
PeerCertificates[domain] = cert
}(domain)
}
这里当err不为Nil时, 如果不return,执行resp.Body.Close()空指针
-
因为当resp异常时,resp.Body必定为Nil;这时不需要显式调用close方法、关闭响应体
其次,需要确保协程内不发生panic或者空指针等严重错误,如果没有defer wg.Done()时,主协程一直等待;
WaitGroup
就不会知道这个协程已经完成,因此wg.Wait()
将会一直阻塞,等待协程报告完成
标准的做法,
确保 defer wg.Done()在协程内其他defer 之前
defer
语句可以保证即使在发生 panic 的情况下,仍然能执行wg.Done()
,从而避免阻塞等待的协程永远等待