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

Go語言實現的可讀性更高的并發神庫

開發 前端
ForEach、Map方法可以更優雅的并發處理切片,代碼簡潔易讀,在實現上Iterator中的并發處理使用atomic來控制只創建一個閉包,避免了GC性能問題

前言

哈嘍,大家好,我是asong;前幾天逛github發現了一個有趣的并發庫-conc,其目標是:

  • 更難出現goroutine泄漏
  • 處理panic更友好
  • 并發代碼可讀性高

從簡介上看主要封裝功能如下:

  • 對waitGroup進行封裝,避免了產生大量重復代碼,并且也封裝recover,安全性更高
  • 提供panics.Catcher封裝recover邏輯,統一捕獲panic,打印調用棧一些信息
  • 提供一個并發執行任務的worker池,可以控制并發度、goroutine可以進行復用,支持函數簽名,同時提供了stream方法來保證結果有序
  • 提供ForEach、map方法優雅的處理切片

接下來就區分模塊來介紹一下這個庫;

倉庫地址:https://github.com/sourcegraph/conc

WatiGroup的封裝

Go語言標準庫有提供sync.waitGroup控制等待goroutine,我們一般會寫出如下代碼:

func main(){
var wg sync.WaitGroup
for i:=0; i < 10; i++{
wg.Add(1)
go func() {
defer wg.Done()
defer func() {
// recover panic
err := recover()
if err != nil {
fmt.Println(err)
}
}
// do something
handle()
}
}
wg.Wait()
}

上述代碼我們需要些一堆重復代碼,并且需要單獨在每一個func中處理recover邏輯,所以conc庫對其進行了封裝,代碼簡化如下:

func main() {
wg := conc.NewWaitGroup()
for i := 0; i < 10; i++ {
wg.Go(doSomething)
}
wg.Wait()
}

func doSomething() {
fmt.Println("test")
}

conc庫封裝也比較簡單,結構如下:

type WaitGroup struct {
wg sync.WaitGroup
pc panics.Catcher
}

其自己實現了Catcher類型對recover邏輯進行了封裝,封裝思路如下:

type Catcher struct {
recovered atomic.Pointer[RecoveredPanic]
}

recovered是原子指針類型,RecoveredPanic是捕獲的recover封裝,封裝了堆棧等信息:

type RecoveredPanic struct {
// The original value of the panic.
Value any
// The caller list as returned by runtime.Callers when the panic was
// recovered. Can be used to produce a more detailed stack information with
// runtime.CallersFrames.
Callers []uintptr
// The formatted stacktrace from the goroutine where the panic was recovered.
// Easier to use than Callers.
Stack []byte
}

提供了Try方法執行方法,只會記錄第一個panic的gououtine信息:

func (p *Catcher) Try(f func()) {
defer p.tryRecover()
f()
}

func (p *Catcher) tryRecover() {
if val := recover(); val != nil {
rp := NewRecoveredPanic(1, val)
// 只會記錄第一個panic的goroutine信息
p.recovered.CompareAndSwap(nil, &rp)
}
}

提供了Repanic()方法用來重放捕獲的panic:

func (p *Catcher) Repanic() {
if val := p.Recovered(); val != nil {
panic(val)
}
}

func (p *Catcher) Recovered() *RecoveredPanic {
return p.recovered.Load()
}

waitGroup對此也分別提供了Wait()、WaitAndRecover()方法:

func (h *WaitGroup) Wait() {
h.wg.Wait()

// Propagate a panic if we caught one from a child goroutine.
h.pc.Repanic()
}

func (h *WaitGroup) WaitAndRecover() *panics.RecoveredPanic {
h.wg.Wait()

// Return a recovered panic if we caught one from a child goroutine.
return h.pc.Recovered()
}

wait方法只要有一個goroutine發生panic就會向上拋出panic,比較簡單粗暴;

waitAndRecover方法只有有一個goroutine發生panic就會返回第一個recover的gouroutine信息;

總結:conc庫對waitGrouop的封裝總體是比較不錯的,可以減少重復的代碼;

worker池

conc提供了幾種類型的worker池:

  • ContextPool:可以傳遞context的pool,若有goroutine發生錯誤可以cancel其他goroutine
  • ErrorPool:通過參數可以控制只收集第一個error還是所有error
  • ResultContextPool:若有goroutine發生錯誤會cancel其他goroutine并且收集錯誤
  • RestultPool:收集work池中每個任務的執行結果,并不能保證順序,保證順序需要使用stream或者iter.map;

我們來看一個簡單的例子:

import "github.com/sourcegraph/conc/pool"

func ExampleContextPool_WithCancelOnError() {
p := pool.New().
WithMaxGoroutines(4).
WithContext(context.Background()).
WithCancelOnError()
for i := 0; i < 3; i++ {
i := i
p.Go(func(ctx context.Context) error {
if i == 2 {
return errors.New("I will cancel all other tasks!")
}
<-ctx.Done()
return nil
})
}
err := p.Wait()
fmt.Println(err)
// Output:
// I will cancel all other tasks!
}

在創建pool時有如下方法可以調用:

  • p.WithMaxGoroutines()配置pool中goroutine的最大數量
  • p.WithErrors:配置pool中的task是否返回error
  • p.WithContext(ctx):配置pool中運行的task當遇到第一個error要取消
  • p.WithFirstError:配置pool中的task只返回第一個error
  • p.WithCollectErrored:配置pool的task收集所有error

pool的基礎結構如下:

type Pool struct {
handle conc.WaitGroup
limiter limiter
tasks chan func()
initOnce sync.Once
}

limiter是控制器,用chan來控制goroutine的數量:

type limiter chan struct{}

func (l limiter) limit() int {
return cap(l)
}

func (l limiter) release() {
if l != nil {
<-l
}
}

pool的核心邏輯也比較簡單,如果沒有設置limiter,那么就看有沒有空閑的worker,否則就創建一個新的worker,然后投遞任務進去;

如果設置了limiter,達到了limiter worker數量上限,就把任務投遞給空閑的worker,沒有空閑就阻塞等著;

func (p *Pool) Go(f func()) {
p.init()

if p.limiter == nil {
// 沒有限制
select {
case p.tasks <- f:
// A goroutine was available to handle the task.
default:
// No goroutine was available to handle the task.
// Spawn a new one and send it the task.
p.handle.Go(p.worker)
p.tasks <- f
}
} else {
select {
case p.limiter <- struct{}{}:
// If we are below our limit, spawn a new worker rather
// than waiting for one to become available.
p.handle.Go(p.worker)

// We know there is at least one worker running, so wait
// for it to become available. This ensures we never spawn
// more workers than the number of tasks.
p.tasks <- f
case p.tasks <- f:
// A worker is available and has accepted the task.
return
}
}

}

這里work使用的是一個無緩沖的channel,這種復用方式很巧妙,如果goroutine執行很快避免創建過多的goroutine;

使用pool處理任務不能保證有序性,conc庫又提供了Stream方法,返回結果可以保持順序;

Stream

Steam的實現也是依賴于pool,在此基礎上做了封裝保證結果的順序性,先看一個例子:

func ExampleStream() {
times := []int{20, 52, 16, 45, 4, 80}

stream := stream2.New()
for _, millis := range times {
dur := time.Duration(millis) * time.Millisecond
stream.Go(func() stream2.Callback {
time.Sleep(dur)
// This will print in the order the tasks were submitted
return func() { fmt.Println(dur) }
})
}
stream.Wait()

// Output:
// 20ms
// 52ms
// 16ms
// 45ms
// 4ms
// 80ms
}

stream的結構如下:

type Stream struct {
pool pool.Pool
callbackerHandle conc.WaitGroup
queue chan callbackCh

initOnce sync.Once
}

queue是一個channel類型,callbackCh也是channel類型 - chan func():

type callbackCh chan func()

在提交goroutine時按照順序生成callbackCh傳遞結果:

func (s *Stream) Go(f Task) {
s.init()

// Get a channel from the cache.
ch := getCh()

// Queue the channel for the callbacker.
s.queue <- ch

// Submit the task for execution.
s.pool.Go(func() {
defer func() {
// In the case of a panic from f, we don't want the callbacker to
// starve waiting for a callback from this channel, so give it an
// empty callback.
if r := recover(); r != nil {
ch <- func() {}
panic(r)
}
}()

// Run the task, sending its callback down this task's channel.
callback := f()
ch <- callback
})
}

var callbackChPool = sync.Pool{
New: func() any {
return make(callbackCh, 1)
},
}

func getCh() callbackCh {
return callbackChPool.Get().(callbackCh)
}

func putCh(ch callbackCh) {
callbackChPool.Put(ch)
}

ForEach和map

ForEach

conc庫提供了ForEach方法可以優雅的并發處理切片,看一下官方的例子:

圖片

conc庫使用泛型進行了封裝,我們只需要關注handle代碼即可,避免冗余代碼,我們自己動手寫一個例子:

func main() {
input := []int{1, 2, 3, 4}
iterator := iter.Iterator[int]{
MaxGoroutines: len(input) / 2,
}

iterator.ForEach(input, func(v *int) {
if *v%2 != 0 {
*v = -1
}
})

fmt.Println(input)
}

ForEach內部實現為Iterator結構及核心邏輯如下:

type Iterator[T any] struct {
MaxGoroutines int
}
func (iter Iterator[T]) ForEachIdx(input []T, f func(int, *T)) {
if iter.MaxGoroutines == 0 {
// iter is a value receiver and is hence safe to mutate
iter.MaxGoroutines = defaultMaxGoroutines()
}

numInput := len(input)
if iter.MaxGoroutines > numInput {
// No more concurrent tasks than the number of input items.
iter.MaxGoroutines = numInput
}

var idx atomic.Int64
// 通過atomic控制僅創建一個閉包
task := func() {
i := int(idx.Add(1) - 1)
for ; i < numInput; i = int(idx.Add(1) - 1) {
f(i, &input[i])
}
}

var wg conc.WaitGroup
for i := 0; i < iter.MaxGoroutines; i++ {
wg.Go(task)
}
wg.Wait()
}

可以設置并發的goroutine數量,默認取的是GOMAXPROCS ,也可以自定義傳參;

并發執行這塊設計的很巧妙,僅創建了一個閉包,通過atomic控制idx,避免頻繁觸發GC;

map

conc庫提供的map方法可以得到對切片中元素結果,官方例子:

圖片

使用map可以提高代碼的可讀性,并且減少了冗余代碼,自己寫個例子:

func main() {
input := []int{1, 2, 3, 4}
mapper := iter.Mapper[int, bool]{
MaxGoroutines: len(input) / 2,
}

results := mapper.Map(input, func(v *int) bool { return *v%2 == 0 })
fmt.Println(results)
// Output:
// [false true false true]
}

map的實現也依賴于Iterator,也是調用的ForEachIdx方法,區別于ForEach是記錄處理結果;

總結

花了小半天時間看了一下這個庫,很多設計點值得我們學習,總結一下我學習到的知識點:

  • conc.WatiGroup對Sync.WaitGroup進行了封裝,對Add、Done、Recover進行了封裝,提高了可讀性,避免了冗余代碼
  • ForEach、Map方法可以更優雅的并發處理切片,代碼簡潔易讀,在實現上Iterator中的并發處理使用atomic來控制只創建一個閉包,避免了GC性能問題
  • pool是一個并發的協程隊列,可以控制協程的數量,實現上也很巧妙,使用一個無緩沖的channel作為worker,如果goroutine執行速度快,避免了創建多個goroutine
  • stream是一個保證順序的并發協程隊列,實現上也很巧妙,使用sync.Pool在提交goroutine時控制順序,值得我們學習;

小伙伴們有時間可以看一下這個并發庫,學習其中的優點,慢慢進步~

責任編輯:武曉燕 來源: Golang夢工廠
相關推薦

2021-10-09 10:24:53

Java 代碼可讀性

2011-09-22 16:10:09

編程語言

2025-11-07 04:22:00

2017-10-30 15:22:29

代碼可讀性技巧

2021-04-01 16:43:05

代碼可讀性開發

2024-01-31 08:04:43

PygmentsPython

2015-08-27 13:11:18

JavaScript代碼

2022-05-19 14:14:26

go語言限流算法

2024-04-23 08:01:20

面向對象C 語言代碼

2022-08-23 14:57:43

Python技巧函數

2021-06-15 09:12:19

TypeScriptTypeScript Javascript

2022-08-29 00:37:53

Python技巧代碼

2017-12-19 16:24:20

2021-01-26 09:18:27

Shell腳本網站

2019-12-03 09:32:32

JavaScript代碼開發

2022-11-04 11:18:16

代碼優化可讀性

2014-07-29 09:55:33

程序員代碼可讀性

2024-10-11 06:00:00

Python代碼編程

2014-07-28 10:28:25

程序員

2024-10-07 10:00:00

Python代碼編碼
點贊
收藏

51CTO技術棧公眾號

国产日韩1区| 国产又黄又嫩又滑又白| 丰满少妇高潮一区二区| 日本激情在线观看| 9999久久久久| 国产精品美女久久久久aⅴ| 欧美激情精品久久久久久| 婷婷五月色综合| 欧美日韩国产精品综合| 粉嫩av一区二区三区四区五区| 成人免费视频视频| 久久躁日日躁aaaaxxxx| 在线观看的毛片| 香蕉久久国产av一区二区| 亚洲九九视频| 欧洲激情一区二区| 欧美日本亚洲| 日韩三级一区二区三区| 日韩视频一二区| 一区视频在线播放| 国产精品一区二区三区久久久| 在线精品一区二区三区| wwww亚洲| 成人av电影免费观看| 欧美猛交免费看| 做a视频在线观看| аⅴ资源新版在线天堂| 日韩精品福利网| 亚洲色图在线观看| 一本久道综合色婷婷五月| 亚洲色图欧美视频| 激情五月激情综合网| 一区二区亚洲欧洲国产日韩| aa在线免费观看| 天堂av在线7| 亚洲少妇自拍| 欧美成年人在线观看| 天堂av8在线| 色多多视频在线观看| 99久久久国产精品免费蜜臀| 久久久久久久久国产| 性欧美18—19sex性高清| 免费在线国产视频| 99久久精品国产一区| 91av视频在线免费观看| 毛片网站免费观看| 日韩av中字| 欧美国产一区在线| 91日本视频在线| 日本黄色片免费观看| 天堂va欧美ⅴa亚洲va一国产| 在线免费不卡电影| 日本网站免费在线观看| 国产三级视频在线播放线观看| 日本成人在线电影网| 久久精品国产一区| 乱码一区二区三区| 亚洲高清黄色| 色综合久久久久综合| 四虎永久在线精品免费一区二区| 天天操天天射天天舔| 久久av在线| www日韩欧美| jjzzjjzz欧美69巨大| 另类视频一区二区三区| 五月天欧美精品| 欧美主播一区二区三区美女 久久精品人 | 国产人妻黑人一区二区三区| rebdb初裸写真在线观看| 久久亚洲欧美国产精品乐播| 国产精品视频自在线| 中文字幕黄色片| 99久久婷婷国产综合精品电影√| 精品国精品国产| 四季av一区二区| 性xxxxfjsxxxxx欧美| 国产午夜亚洲精品午夜鲁丝片| 91视频九色网站| 国产手机精品视频| 久久久久久黄| 国产精品成av人在线视午夜片| 亚洲女人久久久| 日韩三级av| 91精品国产手机| 欧美视频在线播放一区| 亚洲小少妇裸体bbw| 亚洲日本在线天堂| 日韩电影免费观看高清完整| 亚洲欧美另类视频| 精品一区二区久久久| 久久男人资源视频| 永久免费看mv网站入口| 68国产成人综合久久精品| 精品伊人久久97| 亚洲精品久久久久久| a看欧美黄色女同性恋| 亚洲精品720p| 国偷自产av一区二区三区麻豆| www.神马久久| 国产亚洲视频在线| 97香蕉碰碰人妻国产欧美| 免费看日本一区二区| 国产原创视频在线观看| 激情另类小说区图片区视频区| 91久久久久久| 亚洲精品久久久狠狠狠爱| 日韩成人精品视频| 亚洲free性xxxx护士白浆| 丰满熟女人妻一区二区三| 一区二区三区导航| 欧美精品999| 蜜臀精品一区二区三区| 国产精品一区毛片| 国产欧美婷婷中文| 日韩综合在线观看| 国产精品一区二区男女羞羞无遮挡| 国产精品国产亚洲伊人久久 | 久久久久亚洲| 98视频在线噜噜噜国产| 国产又粗又长视频| 视频一区二区国产| 欧美性一区二区三区| 国产无遮无挡120秒| 欧美日韩午夜| 久久精品免费播放| 91视频免费网址| 在线亚洲观看| 99免费在线观看视频| 亚洲av永久纯肉无码精品动漫| 欧美性猛交xxx高清大费中文| 日韩国产精品久久久久久亚洲| 99re在线视频观看| 幼a在线观看| 欧美午夜激情在线| 欧美国产亚洲一区| 国产专区精品| 欧美一区二区三区在| 欧美另类z0zx974| 欧美色网址大全| 中文字幕欧美国内| 国产在视频线精品视频| 91麻豆国产自产在线观看亚洲| 亚洲最新av网址| 豆国产97在线 | 亚洲| 激情综合亚洲精品| 亚洲图片都市激情| 2021国产在线| 亚洲精品乱码久久久久久久久 | 国产精品性做久久久久久| 色就是色欧美| 黑人巨大精品欧美一区二区桃花岛| 色综合久久久久久久| 无码国产精品一区二区免费式直播 | 国产成人精品免费久久久久 | 亚洲欧美综合久久久| 国产精品爽爽ⅴa在线观看| 免费毛片在线| 国产精品视频第一区| 亚洲熟妇av一区二区三区| 巨胸喷奶水www久久久免费动漫| 欧美欧美午夜aⅴ在线观看| 欧美性猛交久久久乱大交小说| 欧美日韩免费电影| 日韩欧美的一区二区| 97人妻精品一区二区三区免费| 中文在线播放一区二区| 亚洲精品欧美日韩专区| 岛国中文字幕在线| 第一福利永久视频精品 | 国产天堂在线播放视频| 日韩欧美一卡二卡| 免费无码毛片一区二区app| 国产黄色精品网站| 精品综合在线| 最新国产在线观看| 亚洲第一搞黄网站| 亚洲国产成人va在线观看麻豆| 一区中文字幕电影| 中文字幕不卡在线视频极品| 亚洲性猛交富婆| 中文字幕亚洲欧美在线不卡| 国产精品久久久久久久99| 天天躁日日躁狠狠躁欧美巨大小说| 91国产美女在线观看| 欧美一区二区少妇| 亚洲一区二区视频在线观看| 一级在线免费视频| 91精品电影| 国产成人免费电影| 亚洲搞黄视频| 欧美一级日韩不卡播放免费| 天天插天天射天天干| 午夜亚洲视频| aa成人免费视频| mm视频在线视频| 尤物九九久久国产精品的特点| 国产女人18毛片水18精| 天天影视色香欲综合网老头| 国产精品成人无码免费| 国产一区二区三区四区五区入口| 日韩福利影院| 欧美.com| 国产97在线亚洲| 色wwwwww| 欧美色网一区二区| 精品无码在线观看| 国产福利一区二区三区在线视频| 国产91在线免费| 偷偷www综合久久久久久久| 久久99精品久久久久久青青日本| 日本天码aⅴ片在线电影网站| 精品视频久久久| 国产乱色精品成人免费视频| 欧美日韩免费看| 青草影院在线观看| 国产一区在线精品| 国产精品第12页| 国产在线不卡| 国产高清在线一区| 日韩经典一区| 91黑丝高跟在线| 黄页视频在线播放| 亚洲人成电影在线| 日韩在线观看视频网站| 亚洲午夜久久久久久久久电影网 | 日本一级片免费看| 日韩理论在线观看| 日韩精品无码一区二区三区久久久| 亚洲国产精品一区| 国产自产精品| 特黄毛片在线观看| 久久久久久网址| а√天堂8资源在线官网| 亚洲天堂色网站| 天堂成人在线视频| 欧美成人在线直播| 国产精品永久久久久久久久久| 在线亚洲欧美专区二区| 精品欧美一区二区三区免费观看 | 久久99精品久久久久久国产越南 | 久久av一区二区三区亚洲| 美女精品视频在线| 成人做爰www免费看视频网站| jizz免费一区二区三区| 国产福利成人在线| 少妇一区视频| 中国日韩欧美久久久久久久久| 亚洲av成人精品一区二区三区在线播放 | a天堂中文在线官网在线| 一区二区日韩精品| 成人77777| 尤物九九久久国产精品的特点 | 一区高清视频| 久久伊人影院| 91啪国产在线| 九色精品蝌蚪| 亚洲999一在线观看www| 91麻豆精品一二三区在线| 欧美成人免费一级人片100| 在线免费观看黄色网址| 永久免费看mv网站入口亚洲| av资源网站在线观看| 中文字幕精品久久| 色综合久久久久综合一本到桃花网| 在线播放日韩精品| 日本在线www| 久久九九免费视频| 色呦呦视频在线观看| 久久久久中文字幕| 性国裸体高清亚洲| 国产精品视频永久免费播放| 三级资源在线| 久久久久久久成人| 午夜久久中文| 国产精品91在线| 亚洲欧美久久精品| 国产精品久久精品国产| 99久久精品一区二区成人| 国产精品一区二区3区| 国产一区二区| 国产精品我不卡| 免费一区二区三区视频导航| 午夜视频久久久| 成年人在线观看| 精品视频全国免费看| 国产又粗又猛又爽又黄的| 日韩欧美一级精品久久| 丰满岳乱妇国产精品一区| 亚洲精品第一页| 九色在线免费| 欧美三级乱人伦电影| 国产精品玖玖玖| 日韩欧美一卡二卡| 人人妻人人澡人人爽久久av| 亚洲欧洲在线视频| 国产美女av在线| 97香蕉超级碰碰久久免费的优势| 黄色av电影在线播放| 欧美激情二区三区| 欧美国产日韩电影| 懂色一区二区三区av片| 红桃成人av在线播放| 精品产品国产在线不卡| 精品日本12videosex| 免费观看成人在线| 欧美精品国产白浆久久久久| 国产精品大全| 精品国产一区二区三区| 台湾无码一区二区| 欧美激情91| 九九久久九九久久| 欧美成人一品| 99re在线视频免费观看| 国产乱码精品一区二区三区av | 羞羞电影在线观看www| 欧美中在线观看| 黄色在线免费观看网站| 国产精品视频资源| 丝袜美腿一区二区三区动态图| 97精品国产97久久久久久粉红| 成人在线免费小视频| 国产成人在线小视频| 国产精品激情电影| 日本超碰在线观看| 91麻豆swag| caopeng视频| 亚洲中国最大av网站| 久久久久久av无码免费网站| 亚洲精品中文在线影院| 波多野结衣不卡视频| 色94色欧美sute亚洲线路一久 | 国产精品成人免费电影| 国产一区二区三区不卡av| 国产高清不卡av| 欧美国产一级| 美女一区二区三区视频| 91丨九色丨蝌蚪富婆spa| 日韩av在线播放观看| 色婷婷亚洲综合| 特黄视频在线观看| 国产做受高潮69| www.久久东京| 欧美这里只有精品| 丁香婷婷深情五月亚洲| 欧美日韩国产精品综合| 日韩一区二区高清| 在线中文字幕视频观看| 亚洲精品免费av| 在线中文字幕第一区| 中文字幕在线视频一区二区三区 | 疯狂试爱三2浴室激情视频| 欧美系列在线观看| 国产精品探花视频| 日韩视频―中文字幕| 农村妇女一区二区| 亚洲一区二区精品在线| 蜜臀av性久久久久蜜臀aⅴ四虎| 污视频在线观看免费网站| 成人18视频在线播放| 国产一级一级片| 亚洲国产精品嫩草影院久久| 国产福利电影在线播放| 久久av一区二区三区漫画| 鲁大师成人一区二区三区| 国产精品扒开腿做爽爽| 色婷婷av久久久久久久| 搞黄视频在线观看| 国产欧美日韩中文字幕在线| 亚洲成人二区| 亚洲成人精品在线播放| 99国内精品久久| 日日噜噜噜噜人人爽亚洲精品| 亚洲欧洲激情在线| 欧美成人xxxx| 在线观看av的网址| av一区二区三区| 无码人妻丰满熟妇精品区| 中文日韩在线观看| 亚洲五码在线| 国产 福利 在线| 国产精品美女久久久久高潮| 国产伦精品一区二区三区免.费| 欧美国产中文字幕| 偷拍一区二区| 天堂av2020| 亚洲成人1区2区| 国产在线高清| 亚洲sss综合天堂久久| 日韩图片一区| 免费91在线观看| 欧美mv日韩mv| 免费成人美女女| 干日本少妇视频| 337p粉嫩大胆色噜噜噜噜亚洲| 伊人成人在线观看| 亚洲跨种族黑人xxx| 黑人极品ⅴideos精品欧美棵| 久久66热这里只有精品| 久久er精品视频| 色婷婷在线观看视频|