精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

關于Golang錯誤處理的一些思考

開發(fā) 前端
如果你還沒在 error 上栽跟頭,那么當你栽了跟頭時才會哭著想起來,當年為什么沒好好思考和反省錯誤處理這么一個宏大的話題

寫在前面:如果你還沒在 error 上栽跟頭,那么當你栽了跟頭時才會哭著想起來,當年為什么沒好好思考和反省錯誤處理這么一個宏大的話題

關于 Golang 錯誤處理的實踐

Golang 有很多優(yōu)點,這也是它如此流行的主要原因。但是 Go 1 對錯誤處理的支持過于簡單了,以至于日常開發(fā)中會有諸多不便利,遭到很多開發(fā)者的吐槽。這些不足催生了一些開源解決方案。與此同時, Go 官方也在從語言和標準庫層面作出改進。這篇文章將給出幾種常見創(chuàng)建錯誤的方式并分析一些常見問題,對比各種解決方案,并展示了迄今為止(go 1.13)的最佳實踐。

[[338649]]

幾種創(chuàng)建錯誤的方式

首先介紹幾種常見的創(chuàng)建錯誤的方法

基于字符串的錯誤

  1. err1 := errors.New("math: square root of negative number"
  2. err2 := fmt.Errorf("math: square root of negative number %g", x) 

帶有數(shù)據(jù)的自定義錯誤

  1. package serr 
  2.  
  3. import ( 
  4.   "fmt" 
  5.   "github.com/satori/go.uuid" 
  6.   "log" 
  7.   "runtime/debug" 
  8.   "time" 
  9. // 自定義基礎錯誤類型 
  10. type BaseError struct { 
  11.   InnerError error 
  12.   Message    string 
  13.   StackTrace string 
  14.   Misc       map[string]interface{} 
  15.  
  16. func WrapError(err error, message string, messageArgs ...interface{}) BaseError { 
  17.   return BaseError{ 
  18.     InnerError: err, 
  19.     Message:    fmt.Sprintf(message, messageArgs), 
  20.     StackTrace: string(debug.Stack()), 
  21.     Misc:       make(map[string]interface{}), 
  22.   } 
  23.  
  24. func (err *BaseError) Error() string { 
  25. // 實現(xiàn) Error 接口 
  26.   return err.Message 
  27.  
  28. // 具體使用 
  29. // "intermediate" module 
  30. type IntermediateErr struct { 
  31.   error 
  32.  
  33. func runJob(id string) error { 
  34.   const jobBinPath = "/bad/job/binary" 
  35.   isExecutable, err := isGloballyExec(jobBinPath) 
  36.   iferr != nil{ 
  37.     return IntermediateErr{wrapError( err, 
  38.     "cannot run job %q: requisite binaries not available"
  39.     id, )} 
  40.   } else if isExecutable == false { 
  41.     return wrapError( 
  42.       nil, 
  43.       "cannot run job %q: requisite binaries are not executable", id, 
  44.     ) 
  45.   } 
  46.   return exec.Command(jobBinPath, "--id="+id).Run() 
  47. }  
  48.    

拋出問題

開發(fā)中經(jīng)常需要檢查返回的錯誤值并作相應處理。下面給出一個最簡單的示例。

  1. import ( 
  2.    "database/sql" 
  3.    "fmt" 
  4.  
  5. func GetSql() error { 
  6.    return sql.ErrNoRows 
  7.  
  8. func Call() error { 
  9.    return GetSql() 
  10.  
  11. func main() { 
  12.    err := Call() 
  13.    if err != nil { 
  14.       fmt.Printf("got err, %+v\n", err) 
  15.    } 
  16. //Outputs: 
  17. // got err, sql: no rows in result set 

有時需要根據(jù)返回的 error 類型作不同處理,例如:

  1. import ( 
  2.    "database/sql" 
  3.    "fmt" 
  4.  
  5. func GetSql() error { 
  6.    return sql.ErrNoRows 
  7.  
  8. func Call() error { 
  9.    return GetSql() 
  10.  
  11. func main() { 
  12.    err := Call() 
  13.    if err == sql.ErrNoRows { 
  14.       fmt.Printf("data not found, %+v\n", err) 
  15.       return 
  16.    } 
  17.    if err != nil { 
  18.       // Unknown error 
  19.    } 
  20. //Outputs: 
  21. // data not found, sql: no rows in result set 

實踐中經(jīng)常需要為錯誤增加上下文信息后再返回,以方便調(diào)用者了解錯誤場景。例如 Getcall 方法時常寫成:

  1. func Getcall() error { 
  2.    return fmt.Errorf("GetSql err, %v", sql.ErrNoRows) 

不過這個時候 err==sql.ErrNoRows 就不成立了。除此之外,上述寫法都在返回錯誤時都丟掉了調(diào)用棧這個重要的信息。我們需要更靈活、更通用的方式來應對此類問題。

解決方案

針對存在的不足,目前有幾種解決方案。這些方式可以對錯誤進行上下文包裝,并攜帶原始錯誤信息, 還能盡量保留完整的調(diào)用棧

方案 1:github.com/pkg/errors

如果只有錯誤的文本,我們很難定位到具體的出錯地點。雖然通過在代碼中搜索錯誤文本也是有可能找到出錯地點的,但是信息有限。所以,在實踐中,我們往往會將出錯時的調(diào)用棧信息也附加上去。調(diào)用棧對消費方是沒有意義的,從隔離和自治的角度來看,消費方唯一需要關心的就是錯誤文本和錯誤類型。調(diào)用棧對實現(xiàn)者自身才是是有價值的。所以,如果一個方法需要返回錯誤,我們一般會使用 errors.WithStack(err) 或者 errors.Wrap(err,"custom message") 的方式,把此刻的調(diào)用棧加到error里去,并且在某個統(tǒng)一地方記錄日志,方便開發(fā)者快速定位問題。

  1. Wrap 方法用來包裝底層錯誤,增加上下文文本信息并附加調(diào)用棧。一般用于包裝對第三方代碼(標準庫或第三方庫)的調(diào)用。
  2. WithMessage 方法僅增加上下文文本信息,不附加調(diào)用棧。如果確定錯誤已被 Wrap 過或不關心調(diào)用棧,可以使用此方法。注意:不要反復 Wrap ,會導致調(diào)用棧重復
  3. Cause 方法用來判斷底層錯誤 。

現(xiàn)在我們用這三個方法來重寫上面的代碼:

  1. import ( 
  2.    "database/sql" 
  3.    "fmt" 
  4.  
  5.    "github.com/pkg/errors" 
  6.  
  7. func GetSql() error { 
  8.    return errors.Wrap(sql.ErrNoRows, "GetSql failed"
  9.  
  10. func Call() error { 
  11.    return errors.WithMessage(GetSql(), "bar failed"
  12.  
  13. func main() { 
  14.    err := Call() 
  15.    if errors.Cause(err) == sql.ErrNoRows { 
  16.       fmt.Printf("data not found, %v\n", err) 
  17.       fmt.Printf("%+v\n", err) 
  18.       return 
  19.    } 
  20.    if err != nil { 
  21.       // unknown error 
  22.    } 
  23. /*Output
  24. data not found, Call failed: GetSql failed: sql: no rows in result set 
  25. sql: no rows in result set 
  26. main.GetSql 
  27.     /usr/three/main.go:11 
  28. main.Call 
  29.     /usr/three/main.go:15 
  30. main.main 
  31.     /usr/three/main.go:19 
  32. runtime.main 
  33.     ... 
  34. */ 

從輸出內(nèi)容可以看到, 使用 %v 作為格式化參數(shù),那么錯誤信息會保持一行, 其中依次包含調(diào)用棧的上下文文本。使用 %+v ,則會輸出完整的調(diào)用棧詳情。如果不需要增加額外上下文信息,僅附加調(diào)用棧后返回,可以使用 WithStack 方法:

  1. func GetSql() error { 
  2.    return errors.WithStack(sql.ErrNoRows) 

注意:無論是 Wrap , WithMessage 還是 WithStack ,當傳入的 err 參數(shù)為 nil 時, 都會返回nil, 這意味著我們在調(diào)用此方法之前無需作 nil 判斷,保持了代碼簡潔

方案 2:golang.org/x/xerrors

結(jié)合社區(qū)反饋,Go 團隊開始考慮在 Go 2 中簡化錯誤處理的提案。Go 核心團隊成員 Russ Cox 在xerrors中部分實現(xiàn)了提案中的內(nèi)容。它用與 github.com/pkg/errors 相似的思路解決同一問題, 引入了一個新的 fmt 格式化動詞: %w,使用 Is 進行判斷。

  1. import ( 
  2.    "database/sql" 
  3.    "fmt" 
  4.  
  5.    "golang.org/x/xerrors" 
  6.  
  7. func Call() error { 
  8.    if err := GetSql(); err != nil { 
  9.       return xerrors.Errorf("bar failed: %w", GetSql()) 
  10.    } 
  11.    return nil 
  12.  
  13. func GetSql() error { 
  14.    return xerrors.Errorf("GetSql failed: %w", sql.ErrNoRows) 
  15.  
  16. func main() { 
  17.    err := Call() 
  18.    if xerrors.Is(err, sql.ErrNoRows) { 
  19.       fmt.Printf("data not found, %v\n", err) 
  20.       fmt.Printf("%+v\n", err) 
  21.       return 
  22.    } 
  23.    if err != nil { 
  24.       // unknown error 
  25.    } 
  26. /* Outputs: 
  27. data not found, Call failed: GetSql failed: sql: no rows in result set 
  28. bar failed: 
  29.     main.Call 
  30.         /usr/four/main.go:12 
  31.   - GetSql failed: 
  32.     main.GetSql 
  33.         /usr/four/main.go:18 
  34.   - sql: no rows in result set 
  35. */ 

與 github.com/pkg/errors 相比,它有幾點不足:

  • 使用 : %w 代替了 Wrap , 看似簡化, 但失去了編譯期檢查。如果沒有冒號,或 : %w 不位于于格式化字符串的結(jié)尾,或冒號與百分號之間沒有空格,包裝將失效且不報錯;
  • 而且,調(diào)用 xerrors.Errorf 之前需要對參數(shù)進行nil判斷。這完全沒有簡化開發(fā)者的工作

方案 3:Go 1.13 內(nèi)置支持

Go 1.13 將 xerrors 的部分功能(不是全部)整合進了標準庫。它繼承了上面提到的 xerrors 的全部缺點, 并額外貢獻了一項。因此目前沒有使用它的必要。

  1. import ( 
  2.    "database/sql" 
  3.    "errors" 
  4.    "fmt" 
  5.  
  6. func Call() error { 
  7.    if err := GetSql(); err != nil { 
  8.       return fmt.Errorf("Call failed: %w", GetSql()) 
  9.    } 
  10.    return nil 
  11.  
  12. func GetSql() error { 
  13.    return fmt.Errorf("GetSql failed: %w", sql.ErrNoRows) 
  14.  
  15. func main() { 
  16.    err := Call() 
  17.    if errors.Is(err, sql.ErrNoRows) { 
  18.       fmt.Printf("data not found,  %+v\n", err) 
  19.       return 
  20.    } 
  21.    if err != nil { 
  22.       // unknown error 
  23.    } 
  24. /* Outputs: 
  25. data not found,  Call failed: GetSql failed: sql: no rows in result set 
  26. */ 

上面的代碼與 xerrors 版本非常接近。但是它不支持調(diào)用棧信息輸出, 根據(jù)官方的說法, 此功能沒有明確的支持時間。因此其實用性遠低于 github.com/pkg/errors。

Golang 中將來可能的錯誤處理方式

在 Go2 的草案中,我們看到了有關于 error 相關的一些提案,那就是 check/handle 函數(shù)。

我們也許在下一個大版本的 Golang 可以像下面這樣處理錯誤:

  1. import "fmt" 
  2. func game() error { 
  3.     handle err { 
  4.         return fmt.Errorf("dependencies error: %v", err) 
  5.     } 
  6.  
  7.     resource := check findResource() // return resource, error 
  8.     defer func() { 
  9.         resource.Release() 
  10.     }() 
  11.  
  12.     profile := check loadProfile() // return profile, error 
  13.     defer func() { 
  14.         profile.Close() 
  15.     } 
  16.  
  17.     // ... 

感興趣的同學可以關注下這個提案:https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling-overview.md

得出結(jié)論

  • 重要的是要記住,包裝錯誤會使該錯誤成為 API 的一部分。如果您不想將來將錯誤作為 API 的一部分來支持,則不應包裝該錯誤。無論是否包裝錯誤,錯誤文本都將相同。那些試圖理解錯誤的人將得到相同的信息,無論采用哪種方式; 是否要包裝錯誤的選擇取決于是否要給程序提供更多信息,以便他們可以做出更明智的決策,還是保留該信息以保留抽象層。

通過以上對比, 相信你已經(jīng)有了選擇。再明確一下我的看法,如果你正在使用 github.com/pkg/errors ,那就保持現(xiàn)狀吧。目前還沒有比它更好的選擇。如果你已經(jīng)大量使用 golang.org/x/xerrors , 別盲目換成 go 1.13 的內(nèi)置方案。

總的來說,Go 在誕生之初就在各個方面表現(xiàn)得相當成熟、穩(wěn)健。在演進路線上很少出現(xiàn)猶疑和搖擺, 而在錯誤處理方面卻是個例外。除了被廣泛吐槽的 if err != nil 之外, 就連其改進路線也備受爭議、分歧明顯,以致于一個改進提案都會因為壓倒性的反對意見而不得不作出調(diào)整。好在 Go 團隊比以前更加樂于傾聽社區(qū)意見,團隊甚至專門就此問題建了個反饋收集頁面。相信最終大家會找到更好的解決方案。

 

責任編輯:未麗燕 來源: Go Official Blog
相關推薦

2021-09-27 15:33:48

Go 開發(fā)技術

2021-09-27 10:04:03

Go程序處理

2017-12-21 07:54:07

2021-06-10 10:02:19

優(yōu)化緩存性能

2025-06-09 08:01:12

2023-10-28 16:30:19

Golang開發(fā)

2012-12-19 09:36:49

測試自動化測試

2024-12-27 10:51:53

2020-02-03 16:03:36

疫情思考

2009-06-25 09:50:32

JSF

2023-10-26 12:05:14

Golang開發(fā)

2021-08-08 10:44:33

安卓系統(tǒng)開發(fā)者手機廠商

2021-06-10 20:17:04

云網(wǎng)融合超融合

2015-10-12 08:59:57

異步代碼測試

2021-06-15 07:10:14

JavaScript異步編程

2018-06-29 14:51:41

Java健壯性實踐

2025-03-18 09:20:00

Go語言Golang

2021-09-28 06:28:51

EF錯誤用法

2011-11-30 15:57:18

2022-05-06 08:00:51

Golang編程語言Java
點贊
收藏

51CTO技術棧公眾號

国内精品久久久久久99蜜桃| 136福利第一导航国产在线| 老司机午夜精品| 欧美福利视频在线| 一区二区黄色片| 91麻豆精品国产综合久久久| 99欧美精品| 欧美综合另类| 亚洲第一精品夜夜躁人人爽 | 成人不用播放器| 国内成+人亚洲+欧美+综合在线| 97国产精品视频人人做人人爱| 五月激情四射婷婷| 色综合久久中文| 91精品国产美女浴室洗澡无遮挡| 漂亮人妻被中出中文字幕| 草莓福利社区在线| 欧美国产精品一区二区三区| 国产不卡一区二区在线观看| 中文字幕乱妇无码av在线| 亚洲xxxx3d动漫| 日韩av影院| 日韩精品一区二区在线| 欧美精品aaaa| 小h片在线观看| 一区二区三区精品| 黄色高清视频网站| 国产尤物视频在线| 91麻豆国产自产在线观看| 91精品久久久久久蜜桃| 亚洲天堂网在线观看视频| 久久久蜜桃一区二区人| 久久久久中文字幕| 久草视频在线资源| 欧美在线网址| 久久精品亚洲94久久精品| 337人体粉嫩噜噜噜| 欧美三级电影在线| 亚洲国产精品一区二区三区| 中文字幕在线观看视频www| 啪啪av大全导航福利综合导航| 色综合久久六月婷婷中文字幕| 国产综合中文字幕| 日本大胆在线观看| 一区二区久久久久久| 日韩免费视频一区二区| 97视频在线观看播放| 国产av 一区二区三区| 99久久久久久中文字幕一区| 一区二区在线视频| 日本精品久久久久中文| 清纯唯美亚洲综合一区| 在线观看视频99| 国产99在线 | 亚洲| re久久精品视频| 正在播放亚洲1区| 少妇视频在线播放| 欧美国产美女| 久久亚洲国产精品| 九九精品在线观看视频| 在线播放日韩| 欧美在线视频导航| 波多野结衣一区二区三区在线| 日韩黄色在线观看| 国产一区视频在线播放| 国产免费叼嘿网站免费| 国产999精品久久| 精品一区2区三区| 男人天堂网在线| 国产精品私人影院| 91麻豆天美传媒在线| 免费看电影在线| 欧美日韩在线另类| 国内自拍视频一区| 国产精品视频一区二区三区综合 | 99国产在线播放| 粉嫩aⅴ一区二区三区四区五区 | 欧美性孕妇孕交| 国产欧美一区二区三区鸳鸯浴| 亚洲精品成人自拍| 欧美高清另类hdvideosexjaⅴ| 性感美女久久精品| 免费看污污网站| 一区二区三区在线免费看 | 亚洲综合不卡| 欧美二区不卡| 亚洲午夜久久久久久久| 国精产品久拍自产在线网站| 欧美日韩视频| 日韩av高清不卡| 国产偷拍一区二区| 2023国产精品| 欧美做受777cos| 电影一区二区三| 日韩视频一区在线观看| www.久久av| 牛牛国产精品| 国产成人鲁鲁免费视频a| 999久久久久| 久久久久久一二三区| 在线观看17c| 日韩欧美精品电影| 亚洲国产天堂久久综合| 小嫩苞一区二区三区| 国产日韩欧美一区| 亚洲一区二区三区777| 午夜在线视频免费| 亚洲女厕所小便bbb| 欧在线一二三四区| 粉嫩精品导航导航| 久久久精品日本| 欧美三级网站在线观看| 波多野结衣中文字幕一区| 麻豆md0077饥渴少妇| 性欧美hd调教| 亚洲精品乱码久久久久久金桔影视 | 天天爽夜夜爽夜夜爽| 亚洲欧美成人一区二区三区| 天天干天天干天天干天天干天天干| 6080成人| 欧美成人精品xxx| 久久国产香蕉视频| 久久精品一区四区| 国产精品国产亚洲精品看不卡| 欧美韩国日本| 在线亚洲男人天堂| 日韩欧美亚洲精品| 国产在线免费看| 亚洲综合99| 国产欧美日韩一区| 欧美性爽视频| 欧美一区二区在线视频| 免费一级特黄3大片视频| 亚洲免费网站| 麻豆av一区二区三区久久| 国产在线xxx| 日韩免费视频一区| 九九视频免费在线观看| 国产一区二区美女| 资源网第一页久久久| www.国产精品| 中文字幕精品www乱入免费视频| wwwxxx亚洲| 久久天天做天天爱综合色| 蜜臀av色欲a片无码精品一区| 一区二区三区亚洲变态调教大结局| 毛片精品免费在线观看| 国产美女三级无套内谢| 亚洲精品国产品国语在线app| 九九热免费在线观看| 91欧美国产| 91精品在线影院| 成人在线视频亚洲| 欧美videos中文字幕| 久久网一区二区| 99热在这里有精品免费| 日韩av三级在线| 免费久久久久久久久| 国产99久久精品一区二区 夜夜躁日日躁 | 成人精品一区二区三区中文字幕| 国产精品va在线观看无码| 亚洲一区二区三区四区电影| 欧美激情精品久久久久久| 蜜桃久久一区二区三区| 欧美午夜视频一区二区| 人妻视频一区二区| 韩国理伦片一区二区三区在线播放 | 欧美日韩国产在线看| 精品视频—区二区三区免费| 熟女俱乐部一区二区| 日本亚洲欧美天堂免费| 最新视频 - x88av| 国产一区调教| 国产精品福利网站| 免费av毛片在线看| 亚洲成人动漫在线播放| 无码人妻av免费一区二区三区 | 9l国产精品久久久久麻豆| 国产亚洲精品网站| 91综合久久| 国产精品久久久一区二区三区| 国内精彩免费自拍视频在线观看网址| 亚洲欧洲视频在线| 国产巨乳在线观看| 欧美体内谢she精2性欧美| 亚洲精品视频网址| 成人高清av在线| 男女污污的视频| 欧美在线视屏| 日韩欧美国产二区| 粉嫩的18在线观看极品精品| 国产精品久久久久久久7电影| 好操啊在线观看免费视频| 亚洲精品国产美女| 中文字幕永久在线观看| 亚洲一区二区四区蜜桃| 91视频免费在观看| 不卡欧美aaaaa| 极品粉嫩美女露脸啪啪| 国产一区二区你懂的| 免费看啪啪网站| 欧美一性一交| 99国产盗摄| 成人在线不卡| 欧美一区二区三区精品电影| 成人区精品一区二区不卡| 亚洲人成77777在线观看网| 性一交一乱一伧老太| 欧美日韩精品福利| 五月天激情国产综合婷婷婷| 亚洲另类在线一区| 精品人体无码一区二区三区| 91社区在线播放| 少妇高潮一69aⅹ| 麻豆成人免费电影| 黑森林福利视频导航| 一级全黄裸体免费视频| 国产亚洲欧美激情| 人妻av一区二区| 国产精品综合网| 九九热免费在线观看| 久久亚洲视频| 亚洲欧洲日产国码无码久久99| 一区二区三区网站| 一卡二卡3卡四卡高清精品视频| 亚洲精品亚洲人成在线| 国产一区二区三区四区hd| 日韩成人在线观看视频| 国产中文字幕日韩| 国产精品久久久久久吹潮| 国产成人av网| 欧美xx视频| 欧美自拍视频在线观看| 无遮挡爽大片在线观看视频| 国内精品小视频在线观看| 麻豆av在线播放| 欧美成人免费小视频| 精品美女在线观看视频在线观看| 中文精品99久久国产香蕉| av午夜在线| 日韩在线观看网站| 97超碰人人在线| 中文在线不卡视频| 午夜伦理在线| 久久五月天综合| 亚洲综合伊人久久大杳蕉| 成人97在线观看视频| 天堂va在线| 久久久久久成人精品| av手机免费在线观看| 777国产偷窥盗摄精品视频| 美女扒开腿让男人桶爽久久软| 91精品国产网站| 日韩av大片站长工具| 国产精品久久久久久久美男| 小明成人免费视频一区| 国产精品丝袜久久久久久高清 | 欧美自拍丝袜亚洲| 一区二区三区在线免费观看视频| 欧美日本在线播放| 国产成人三级一区二区在线观看一| 欧美一二三四区在线| 免费观看a视频| 国产偷亚洲偷欧美偷精品| 男人的天堂在线视频| 色偷偷综合社区| 超碰在线免费播放| 国模私拍视频一区| 午夜av成人| 91在线观看欧美日韩| 国偷自产av一区二区三区| 精品国产一区二区三区av性色| 亚洲污视频在线观看| 久久成人免费网站| www.四虎精品| 久久精品一区二区| 日韩在线视频网址| 香蕉成人伊视频在线观看| 无码人妻av一区二区三区波多野| 91精品免费在线观看| 天堂在线视频观看| 中文字幕亚洲无线码a| 手机在线免费观看av| 日产日韩在线亚洲欧美| 伊人久久大香伊蕉在人线观看热v 伊人久久大香线蕉综合影院首页 伊人久久大香 | 欧美探花视频资源| 亚洲精品字幕在线| 一区二区在线视频| 55av亚洲| 91精品免费看| 美女亚洲一区| 99久久久精品视频| 蜜臀va亚洲va欧美va天堂| 91超薄肉色丝袜交足高跟凉鞋| 久久精品夜色噜噜亚洲aⅴ| 国产va在线播放| 欧美图区在线视频| 午夜视频福利在线| 久久99热这里只有精品国产| 99re66热这里只有精品4| 99re国产视频| 日韩免费一区| 欧美视频第一区| 丁香激情综合五月| 亚洲一区电影在线观看| 色婷婷亚洲精品| 秋霞网一区二区| 欧美不卡视频一区发布| av在线一区不卡| 久久99精品久久久久久青青日本| 欧美一区二区三区久久精品茉莉花 | 国产日韩一区| 在线观看免费成人av| 电影一区中文字幕| 成人av免费电影| 99久久精品网| 日本免费观看网站| 91美女视频网站| 国产一级淫片免费| av资源中文在线| 成人黄色午夜影院| 欧洲美女日日| av免费中文字幕| 99久久久免费精品国产一区二区| 欧美日韩一级大片| 欧美一区二区三区视频在线观看| h视频网站在线观看| 欧洲日本亚洲国产区| 国产乱论精品| 国产免费一区二区视频| 国产精品123| 欧美xxxx黑人xyx性爽| 91精品国产综合久久精品图片| 永久免费av在线| 国产精品老女人精品视频| 国产一区二区三区四区五区传媒| 日本精品免费在线观看| 99精品视频中文字幕| 午夜影院在线看| 亚洲激情视频网| 日本黄色免费在线| 欧美日韩国产一二| 先锋a资源在线看亚洲| 日本丰满少妇裸体自慰| 岛国av午夜精品| 男人的天堂在线| 国产精品久久久久91| 欧美综合视频| 午夜剧场高清版免费观看| 亚洲欧美在线aaa| 91丨九色丨丰满| 欧美成年人视频网站欧美| 五月亚洲婷婷| 国产原创中文在线观看| 99久久精品国产观看| 亚洲精品77777| 亚洲美女精品成人在线视频| 日韩欧美少妇| 亚洲 欧洲 日韩| 国产高清久久久久| 国产精品白浆一区二小说| 日韩高清不卡av| 日韩制服一区| 欧美精品久久96人妻无码| 成人的网站免费观看| 亚洲天堂av片| 中文字幕亚洲无线码在线一区| 久久夜夜久久| 400部精品国偷自产在线观看| 成人免费视频视频| 久久久久在线视频| 粗暴蹂躏中文一区二区三区| 91精品国产乱码久久久竹菊| 日韩av黄色网址| 国产精品久久久久久久午夜片| 国产黄色高清视频| 91po在线观看91精品国产性色| 欧美日韩在线网站| 女人扒开腿免费视频app| 婷婷激情综合网| 午夜激情视频在线观看| 国产伦精品一区二区三区照片| 免费永久网站黄欧美| 在线观看黄网址| 亚洲激情在线观看| 婷婷久久免费视频| 欧美啪啪免费视频| 国产精品电影一区二区| 熟妇人妻一区二区三区四区| 国产精品r级在线| 国产一区二区中文| 美女100%露胸无遮挡| 精品成人一区二区| 精品久久99| 国产极品尤物在线| 最新热久久免费视频| 天堂a中文在线| 3d精品h动漫啪啪一区二区| 天堂资源在线中文精品| 国产一级在线观看视频|