精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

免费精品国产的网站免费观看| 欧美理论片在线播放| 欧美aaaaa成人免费观看视频| 北条麻妃在线一区二区| 无码人妻一区二区三区免费n鬼沢| av福利在线导航| 国产欧美日韩一区二区三区在线观看 | 亚洲观看高清完整版在线观看| 免费在线成人av| 国产女人高潮的av毛片| 六月天综合网| 欧美成人免费观看| 亚洲码无人客一区二区三区| 欧美日韩中出| 欧美在线观看一二区| 欧美乱大交xxxxx潮喷l头像| 永久av在线| 26uuu久久天堂性欧美| 91深夜福利视频| 久久久久久久亚洲| 99在线精品免费视频九九视| 久久精品久久久久| 成人在线一级片| 精品视频高潮| 日韩一区二区电影| 黄色手机在线视频| 欧美极品免费| 精品久久久久久久久久久| www婷婷av久久久影片| 香蕉视频免费在线播放| 久久久久国产成人精品亚洲午夜| 国产精品免费一区二区| 国产深喉视频一区二区| 蜜乳av一区二区三区| 国产成人精品久久二区二区| 日韩三级小视频| 狠狠88综合久久久久综合网| 久久久精品国产网站| 992在线观看| 精品国产乱码| 亚洲一区www| 偷拍夫妻性生活| 亚洲肉体裸体xxxx137| 亚洲第一精品福利| 国内自拍偷拍视频| 伊人久久噜噜噜躁狠狠躁| 欧美一区二区免费| 伊人精品视频在线观看| 欧美综合影院| 欧美高清视频在线高清观看mv色露露十八| 嫩草av久久伊人妇女超级a| 日本在线影院| 日本精品视频一区二区| wwwwww.色| 色猫猫成人app| 欧美日韩黄色一区二区| 男女视频在线看| 丁香婷婷久久| 欧美丰满一区二区免费视频| 中文字幕22页| 亚洲精品午夜| 亚洲第一区第一页| 黄色录像a级片| 免费精品国产| 精品国产一区av| 青春草免费视频| 黄色精品网站| 日本精品性网站在线观看| 91久久国产综合久久91| 久久se这里有精品| 99久久精品免费看国产一区二区三区| 成人毛片在线精品国产| 91视频精品在这里| 色999五月色| 国产日产一区二区| 亚洲成av人片在线| aa在线免费观看| aaaa欧美| 亚洲第一网站免费视频| 9.1成人看片| 久久一区二区中文字幕| 九九九热精品免费视频观看网站| 日产精品久久久久| 日韩高清电影一区| 春色成人在线视频| 国产高清一区在线观看| 亚洲精品日韩一| 亚洲欧洲日产国码无码久久99 | 国产精品天天狠天天看| 精品国产一级片| 2020国产精品自拍| 中文字幕一区综合| 国产在线美女| 欧美日韩中文字幕一区二区| 欧美一区二区三区影院| 中文有码一区| 久久99国产精品久久久久久久久| www欧美在线| 九九久久精品视频| 久久久久一区二区| 亚洲图区一区| 欧美亚洲一区二区在线观看| 折磨小男生性器羞耻的故事| 日韩av久操| 69视频在线播放| 国产视频一区二区三| 久久精品视频免费| 男人添女荫道口喷水视频| 免费日韩成人| 亚洲码在线观看| 久久久久久久国产精品毛片| 久久精品免费观看| 欧美一区二区福利| 黄色漫画在线免费看| 69成人精品免费视频| 熟女俱乐部一区二区视频在线| 欧美三级网页| 成人午夜小视频| 最新97超碰在线| 欧美性生交大片免网| 国产女主播在线播放| 一区二区蜜桃| 成人精品一区二区三区| 国产视频福利在线| 欧美性开放视频| 日本精品一二三| 一本到12不卡视频在线dvd| 国产精品视频中文字幕91| 亚洲 国产 欧美 日韩| 怡红院av一区二区三区| 五月激情五月婷婷| 成人无号精品一区二区三区| 日本91av在线播放| 午夜影院在线视频| 午夜精品福利一区二区蜜股av| 九九热视频免费| 999久久久精品国产| 国产精品偷伦视频免费观看国产| 二人午夜免费观看在线视频| 狠狠躁夜夜躁人人爽天天天天97| 久久久久9999| 亚洲免费综合| 欧美凹凸一区二区三区视频| 午夜激情电影在线播放| 日韩精品在线视频观看| 日本系列第一页| 99久久免费视频.com| 国产主播自拍av| 免费日韩一区二区三区| 久久免费精品视频| 性插视频在线观看| 色婷婷久久久综合中文字幕| 国产一区二区三区四区五区六区| 米奇777在线欧美播放| 欧美最大成人综合网| 婷婷综合六月| 最近中文字幕2019免费| 在线观看免费视频a| 亚洲人123区| av不卡中文字幕| 国产亚洲精品v| 日本成人黄色| 欧美高清你懂的| 欧美日韩国产123| 天天操天天射天天| 日本黄色一区二区| 性生交大片免费全黄| 国产成人精品一区二区三区网站观看| 男女激情免费视频| 天天躁日日躁狠狠躁欧美| 国产精品成人一区| 免费高清在线观看| 精品欧美久久久| 免费黄色av片| 亚洲欧美日韩一区| 日本黄色免费观看| 日产国产欧美视频一区精品| 一道本在线观看视频| 精品少妇一区| 成人黄色在线免费| av人人综合网| 综合av色偷偷网| 成人免费公开视频| 在线观看视频一区二区欧美日韩| 三级av在线免费观看| 成人99免费视频| 亚洲免费一级视频| 激情欧美国产欧美| 亚洲人久久久| 免费观看成人www动漫视频| 国产免费一区二区三区在线能观看| av小次郎在线| 亚洲视频视频在线| 亚洲精品无amm毛片| 91黄色免费版| 一级片免费网址| 成人欧美一区二区三区在线播放| 中文字幕日韩三级片| 麻豆高清免费国产一区| 久久国产精品视频在线观看| 999视频精品| 久精品国产欧美| 日韩三级av高清片| 国产精品久久久久久久一区探花| 国产精品一品| 久久人人爽人人爽爽久久| 欧美精品a∨在线观看不卡| 日韩一区二区在线看| 这里只有精品免费视频| 婷婷亚洲久悠悠色悠在线播放| 黄色片网站在线播放| 久久久久国产精品麻豆ai换脸| 五月天丁香社区| 国产在线精品一区二区三区不卡| 免费在线观看的毛片| 亚洲精品三级| 成人小视频在线观看免费| 国产精品久久久久蜜臀| 日韩一区不卡| 亚洲警察之高压线| 国内不卡一区二区三区| 五月亚洲婷婷| 亚洲精品女av网站| 欧美成人免费全部网站| 国产精品免费一区| 欧美成人黑人| 奇米四色中文综合久久| 色戒汤唯在线| 91精品国产91久久久| www欧美xxxx| 欧美精品video| 久草在线视频资源| 欧美高跟鞋交xxxxhd| 国产一二区在线| 久久夜色精品国产亚洲aⅴ| 午夜小视频在线| 视频一区视频二区国产精品| 91涩漫在线观看| 在线播放国产一区二区三区| sese一区| 日韩最新免费不卡| 麻豆影视国产在线观看| 色吧影院999| 欧美天天影院| 欧美成人免费视频| 手机电影在线观看| 久久男人的天堂| 激情黄产视频在线免费观看| 2019中文字幕在线观看| gay欧美网站| 国产精品日韩在线播放| 日日夜夜精品| 亚洲综合在线小说| aaa国产精品| 亚洲精品美女视频| 国产精品视频永久免费播放| www.综合| 日韩av免费网站| 国产精品亚洲一区二区三区在线观看| 日本一区二区三区四区视频| 日韩a**中文字幕| 国产精品视频在线播放| 国产剧情一区二区在线观看| 亚洲综合在线小说| 第一区第二区在线| 欧美国产一区二区在线| 欧美午夜精品一区二区三区电影| 一区二区三区av在线| 欧美破处大片在线视频| 国产九九九九九| 免费不卡在线视频| 一区二区三区人妻| 粉嫩绯色av一区二区在线观看| 久久性爱视频网站| 久久久99精品久久| 污软件在线观看| 精品成人国产在线观看男人呻吟| 日本熟妇一区二区三区| 91.成人天堂一区| 女人18毛片水真多18精品| 亚洲午夜久久久久久久| 黄色片网站在线观看| 97国产精品久久| 国产精品伦一区二区| 成人自拍偷拍| 色777狠狠狠综合伊人| 欧美精品久久久久久久自慰| 日韩国产精品久久久久久亚洲| 亚洲热在线视频| 久久久精品日韩欧美| 永久免费看黄网站| 色呦呦日韩精品| 99久久精品国产一区二区成人| 亚洲精品一区二三区不卡| 国产在线高清理伦片a| 欧美制服第一页| 亚洲精品aⅴ| 亚洲日本精品一区| 国产欧美激情| 久久婷婷中文字幕| 国产色婷婷亚洲99精品小说| 久久久久久久久艹| 欧美日韩一区二区在线观看视频| 黄色小视频免费在线观看| 最近2019中文字幕一页二页| 激情国产在线| 成人av免费看| 羞羞答答成人影院www| av免费在线播放网站| 成人免费福利片| 青草影院在线观看| 欧美性xxxxxx少妇| 瑟瑟在线观看| 欧美日产国产成人免费图片| 成人黄色毛片| 玛丽玛丽电影原版免费观看1977| 欧美精品aa| 色婷婷一区二区三区av免费看| 久久久亚洲综合| 国产精品999在线观看| 欧美一区二区三区在线| 一广人看www在线观看免费视频| 日本欧美在线视频| 欧美电影在线观看完整版| 免费看污污视频| 国产在线视频一区二区| 久久一级免费视频| 欧美三级电影在线看| 成人午夜在线观看视频| 国产精品678| 免费久久精品| 欧在线一二三四区| 国产午夜一区二区三区| 亚洲天堂视频网站| 亚洲精品国产精品久久清纯直播| 色呦呦在线资源| 91精品天堂| 欧美私人啪啪vps| 国产成人精品综合久久久久99| 亚洲乱码国产乱码精品精的特点 | 97人妻人人揉人人躁人人| 欧美三级欧美成人高清www| 偷拍精品一区二区三区| 91精品国产99| 伊人久久大香线蕉综合网蜜芽| 337p粉嫩大胆噜噜噜鲁| 337p粉嫩大胆色噜噜噜噜亚洲| 国内自拍视频在线播放| 亚洲精品一区二区在线| 天天综合网站| 亚洲一区在线免费| 国产一区二区女| 国产网友自拍视频| 亚洲精品电影在线观看| 亚洲黄色网址| 亚洲春色在线| 国产精品77777竹菊影视小说| 九九热视频精品| 亚洲精品乱码久久久久久按摩观| 成人福利av| 亚洲免费精品视频| 国产主播一区二区| 国产午夜福利片| 亚洲毛片在线免费观看| a成人v在线| 亚洲av首页在线| 成人精品电影在线观看| 中文字幕亚洲乱码熟女1区2区| 亚洲色图五月天| 成人在线分类| 亚洲 高清 成人 动漫| 国产欧美日韩在线观看| 精品人妻一区二区三区日产乱码 | av电影一区二区三区| 国产一区二区按摩在线观看| 国产精品a成v人在线播放| 亚洲欧美中文字幕| 麻豆精品久久| 春日野结衣av| 国产精品理伦片| 成 人 黄 色 片 在线播放| 欧美中文字幕第一页| 久久精品国产大片免费观看| av不卡中文字幕| 欧美色图在线观看| 888av在线视频| 日韩欧美亚洲日产国产| 国产成人亚洲综合色影视| 国产字幕在线观看| 欧美激情国产精品| 国产一区国产二区国产三区| 亚洲美女精品视频| 欧美色综合久久| 色综合桃花网| 可以在线看黄的网站| 国产午夜三级一区二区三| 亚洲精品一区二区口爆| 国产精品私拍pans大尺度在线| 影音先锋国产精品| www.5588.com毛片|