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

Go語言之深入理解函數

開發 后端
在計算機程序設計中,函數其實是一種抽象概念,是一種編程接口;通過抽象,能夠實現將復雜的系統分解成各種包裝了復雜算法的不透明接口,方便彼此相互調用,實現分層、擴展性、便利性等等。

[[429304]]

概念

在計算機程序設計中,函數其實是一種抽象概念,是一種編程接口;通過抽象,能夠實現將復雜的系統分解成各種包裝了復雜算法的不透明接口,方便彼此相互調用,實現分層、擴展性、便利性等等。

具體來講,函數一般是指一段獨立的、可重復利用的程序邏輯片段,用來方便其他函數調用;英文名稱是function,有時候也稱為method、routine。

編譯器最終將函數編譯為機器指令,保存在可執行文件中。

在進程的內存空間中,一個函數只不過是一段包含機器指令的連續內存區域;僅僅從結構上來講,和數組沒什么區別。

在Go語言中,函數(function)是一等公民(first-class citizen),不僅僅是代碼片段,也是一種數據類型;和其他數據類型一樣有自己的類型信息。

函數類型

函數類型的定義有多處,它們是等價的。

在runtime/type.go源文件中定義如下:

  1. type functype struct { 
  2.     typ      _type 
  3.     inCount  uint16 
  4.     outCount uint16 

在reflect/type.go和internal/reflectlite/type.go源文件中定義如下:

  1. // funcType represents a function type. 
  2. // 
  3. // A *rtype for each in and out parameter is stored in an array that 
  4. // directly follows the funcType (and possibly its uncommonType). So 
  5. // a function type with one method, one input, and one output is
  6. // 
  7. //  struct { 
  8. //    funcType 
  9. //    uncommonType 
  10. //    [2]*rtype    // [0] is in, [1] is out 
  11. //  } 
  12. type funcType struct { 
  13.   rtype 
  14.   inCount  uint16 
  15.   outCount uint16 // top bit is set if last input parameter is ... 

從funcType結構體的注釋中可以看到,函數類型的信息其實非常復雜。

其實完整的函數類型定義如下偽代碼所示:

  1. type funcType struct { 
  2.     rtype           // 基礎類型信息  
  3.     inCount  uint16 // 參數數量 
  4.     outCount uint16 // 返回值數量 
  5.     uncommon uncommonType     // 方法信息 
  6.     inTypes  [inCount]*rtype  // 參數類型列表 
  7.     outTypes [outCount]*rtype // 返回值類型列表 
  8.     methods  [uncommon.mcount]method // 方法列表 

uncommonType和method定義在reflect/type.go源文件中,用于存儲和解析類型的方法信息。

  1. type uncommonType struct { 
  2.     pkgPath nameOff  // 包路徑名稱偏移量 
  3.     mcount  uint16   // 方法的數量 
  4.     xcount  uint16   // 公共導出方法的數量 
  5.     moff    uint32   // methods相對本對象起始地址的偏移量 
  6.     _       uint32   // unused 
  1. // 非接口類型的方法 
  2. type method struct { 
  3.     name nameOff // 方法名稱偏移量 
  4.     mtyp typeOff // 方法類型偏移量 
  5.     ifn  textOff // 通過接口調用時的地址偏移量;接口類型本文不介紹 
  6.     tfn  textOff // 直接類型調用時的地址偏移量 
  1. type nameOff int32 // offset to a name 
  2. type typeOff int32 // offset to an *rtype 
  3. type textOff int32 // offset from top of text section 
  • nameOff 是相對 .rodata 節起始地址的偏移量。
  • typeOff 是相對 .rodata 節起始地址的偏移量。
  • textOff 是相對 .text 節起始地址的偏移量。
  • 關于 reflect.name的介紹,請閱讀 內存中的整數 。

函數類型結構分布示意圖

完整的函數類型信息結構分布如下圖所示:

每一種函數都有自己的類型信息,只不過有的函數簡單,有的函數復雜,并不是每一種函數類型包含上圖中的所有字段。

簡單的函數類型信息結構分布可能如下圖所示:

或者

備注:以上示意圖中的淺灰色塊表示內存對齊的填充,不存儲任何數據。

當然,函數也可能有參數無返回值,函數還可能無參數有返回值,它們的類型信息結構還會有一點點不同,想象一下,不過只是一種簡化的結構罷了。

通過本文的內存分析,我們將會了解函數類型的每一個細節。

環境

  1. OS : Ubuntu 20.04.2 LTS; x86_64 
  2.  
  3. Go : go version go1.16.2 linux/amd64 

聲明

操作系統、處理器架構、Go版本不同,均有可能造成相同的源碼編譯后運行時的寄存器值、內存地址、數據結構等存在差異。

本文僅包含 64 位系統架構下的 64 位可執行程序的研究分析。

本文僅保證學習過程中的分析數據在當前環境下的準確有效性。

本文僅討論普通函數和聲明的函數類型,不討論接口、實現、閉包等知識點。

代碼清單

  1. package main 
  2.  
  3. import ( 
  4.   "errors" 
  5.   "fmt" 
  6.   "reflect" 
  7.  
  8. // 聲明函數類型 
  9. type calc func(a, b int) (sum int
  10.  
  11. // 私有的方法 -> package scope 
  12. //go:noinline 
  13. func (f calc) foo(a, b intint { 
  14.   return f(a, b) + 1 
  15.  
  16. // Ree 公共導出的方法 -> public scope 
  17. //go:noinline 
  18. func (f calc) Ree(a, b intint { 
  19.   return f(a, b) - 1 
  20.  
  21. func main() { 
  22.   // 普通函數 
  23.   Print(fmt.Printf) 
  24.   // 函數類型實例 
  25.   var add calc = func(a, b int) (sum int) { 
  26.     return a + b 
  27.   } 
  28.   fmt.Println(add.foo(1, 2)) 
  29.   fmt.Println(add.Ree(1, 2)) 
  30.   Print(add
  31.   // 匿名函數 
  32.   Print(func() { 
  33.     fmt.Println("hello anonymous function"
  34.   }) 
  35.   // 方法;閉包 
  36.   f := errors.New("hello error").Error 
  37.   Print(f) 
  38.  
  39.  
  40. //go:noinline 
  41. func Print(i interface{}) { 
  42.   v := reflect.ValueOf(i) 
  43.   fmt.Println("類型", v.Type().String()) 
  44.   fmt.Println("地址", v) 
  45.   fmt.Println() 

運行效果

以上代碼清單,主要打印輸出了四個函數的類型和內存地址。

編譯并運行,輸出如下:

在本文的內存分析過程中,存在許多通過偏移量計算內存地址的操作。

主要涉及到 .text 和 .rodata 兩個 section,在本程序中它們的信息如下:

普通函數

以fmt.Printf這個常用的函數為例,研究普通函數的類型信息。

從上面的運行輸出結果可以看到,fmt.Printf函數類型的字符串表示形式為:

  1. func(string, ...interface {}) (int, error) 

動態調試

在Print函數入口處設置斷點,查看fmt.Printf函數的類型信息。

將fmt.Printf函數的類型信息繪制成圖表如下:

 

  • rtype.size = 8
  • rtype.ptrdata = 8
  • rtype.hash = 0xd9fb8597
  • rtype.tflag = 2 = reflect.tflagExtraStar
  • rtype.align = 8
  • rtype.fieldAlign = 8
  • rtype.kind = 0x33
  • rtype.equal = 0 = nil
  • rtype.str = 0x00005c90 => *func(string, ...interface {}) (int, error)
  • rtype.ptrToThis = 0
  • funcType.inCount = 2
  • funcType.outCount = 0x8002
  • funcType.inTypes = [ 0x4a4860, 0x4a2f80 ]
  • funcType.outTypes = [ 0x4a41e0, 0x4a9860 ]

指針常量

函數對象的大小是8字節(rtype.size),而且包含8字節的指針數據(rtype.ptrdata),所以我們可以將函數對象視為指針。

也就是說fmt.Printf其實是一個指針,只不過這個指針是一個不可變的常量。這與C/C++是一致的,函數名稱就是一個指針常量。

類型名稱

rtype.tflag = 2 = reflect.tflagExtraStar

fmt.Printf函數有自己的數據類型,但是該類型并沒有名稱。

數據類別

數據類別(Kind)的計算方法如下:

  1. const kindMask = (1 << 5) - 1 
  2.  
  3. func (t *rtype) Kind() Kind { return Kind(t.kind & kindMask) } 

0x33 & 31 = 19 = reflect.Func

可變參數

fmt.Printf函數的參數數量(funcType.inCount)是2,返回值數量也是2,可funcType.outCount值為什么是0x8002?

原因是funcType.outCount字段不但需要記錄函數返回值的數量,還需要標記函數最后一個參數是否是可變參數類型;如果是,將funcType.outCount字段值的最高位設置為1。

在reflect/type.go源文件中,判斷可變參數的方法如下:

  1. func (t *rtype) IsVariadic() bool { 
  2.     if t.Kind() != Func { 
  3.         panic("reflect: IsVariadic of non-func type " + t.String()) 
  4.     } 
  5.     tt := (*funcType)(unsafe.Pointer(t)) 
  6.     return tt.outCount&(1<<15) != 0 

返回值數量的計算方式是:

  1. outCount := funcType.outCount & (1<<15 - 1) 

令人好奇的是,可變參數標記怎么沒有保存在funcType.outCount字段中。

參數與返回值類型

在fmt.Printf函數定義中,參數和返回值的類型依次是:

  • string
  • ...interface{}
  • int
  • error

在內存的函數類型信息中,保存的是參數和返回值的類型指針;通過這些指針查看它們的類型信息如下:

通過內存數據可以看到,fmt.Printf函數的參數和返回值的數據類別(Kind)如下:

  • reflect.String
  • reflect.Slice
  • reflect.Int
  • reflect.Interface

關于整數及其類型的詳細介紹,請閱讀 內存中的整數 。

關于字符串及其類型的詳細介紹,請閱讀 內存中的字符串 。

在Go語言中,error比較特殊,它既是一個關鍵字,又是一個接口定義。關于接口類型,之后將發布專題文章進行深入解析,暫不介紹。

關于slice,內存中的slice 一文曾對 []int 進行了詳細介紹 。

很明顯,fmt.Printf函數的第二個參數不是[]int,通過內存數據來看一看具體是什么類型的slice。

通過上圖可以看到,編譯器將源碼中的可變參數類型...interface{}編譯為[]interface {},從而把可變參數變成一個參數。

這種處理可變參數的方式,和Java語言非常相似。

通過對fmt.Printf函數的類型深入分析和了解,我們就很容易理解反射包(reflect)中函數相關的接口了;有興趣的話可以去看一看源碼實現,相信對比fmt.Printf函數的類型信息,是比較簡單的。

  1. type Type interface { 
  2.     ...... // 省略無關接口 
  3.     IsVariadic() bool 
  4.     NumIn() int 
  5.     NumOut() int 
  6.     In(i int) Type 
  7.     Out(i int) Type 
  8.     ...... // 省略無關接口 

聲明的函數類型

在Go語言中,通過type關鍵字可以定義任何數據類型,非常非常地強悍。

在本文的代碼清單中,我們就使用type關鍵字定義了calc類型,這明顯是一個函數類型。

type calc func (a, b int) (sum int)

這種類型與fmt.Printf函數類型有什么區別嗎?使用上述相同的方法,我們來深入研究下。

動態調試

從內存數據可以看出,calc類型的add變量指向一個匿名函數,該匿名函數被編譯器命名為main.main.func1。

calc的類型信息非常復雜,共128個字節,整理成圖表如下:

  • rtype.size = 8
  • rtype.ptrdata = 8
  • rtype.hash = 0x405feca1
  • rtype.tflag = 7 = reflect.tflagUncommon | reflect.tflagExtraStar | reflect.tflagNamed
  • rtype.align = 8
  • rtype.fieldAlign = 8
  • rtype.kind = 0x33
  • rtype.equal = 0 = nil
  • rtype.str = 0x00002253 => *main.calc
  • rtype.ptrToThis = 0x0000ec60
  • funcType.inCount = 2
  • funcType.outCount = 1
  • funcType.inTypes = [ 0x4a41e0, 0x4a41e0 ]
  • funcType.outTypes = [ 0x4a41e0 ]
  • uncommonType.pkgPath = 0x0000034c => main
  • uncommonType.mcount = 2
  • uncommonType.xcount = 1
  • uncommonType.moff = 0x48
  • method[0].name = 0x000001a8 => Ree
  • method[0].mtyp = 0xffffffff
  • method[0].ifn = 0x00098240
  • method[0].tfn = 0x00098240
  • method[1].name = 0x000001f6 => foo
  • method[1].mtyp = 0xffffffff
  • method[1].ifn = 0x000981e0
  • method[1].tfn = 0x000981e0

類型名稱

rtype.tflag字段包含reflect.tflagNamed標記,表示該類型是有名稱的。

calc類型的名稱為calc,獲取方式定義在reflect/type.go源文件中:

  1. func (t *rtype) hasName() bool { 
  2.     return t.tflag&tflagNamed != 0 
  3.  
  4. func (t *rtype) Name() string { 
  5.     if !t.hasName() { 
  6.         return "" 
  7.     } 
  8.     s := t.String() 
  9.     i := len(s) - 1 
  10.     for i >= 0 && s[i] != '.' { 
  11.         i-- 
  12.     } 
  13.     return s[i+1:] 
  14.  
  15. func (t *rtype) String() string { 
  16.     s := t.nameOff(t.str).name() 
  17.     if t.tflag&tflagExtraStar != 0 { 
  18.         return s[1:] 
  19.     } 
  20.     return s 

類型指針

  1. rtype.ptrToThis = 0x0000ec60 

該值是相對程序 .rodata section 的偏移量。在本程序中,.rodata section 的起始地址是 0x49a000。

calc類型的指針類型為*calc,類型信息保存在地址 0x49a000+0x0000ec60處。關于指針類型本文不再進一步介紹。

參數和返回值

calc類型有2個參數和1個返回值,而且都是int類型(信息保存在0x4a41e0地址處)。

類型方法

方法本質上就是函數。

在 A Tour of Go (https://tour.golang.org/methods/1) 中,對函數的定義為:

  1. A method is a function with a special receiver argument. 

calc是函數類型,函數類型居然能擁有自己的方法,確實是巧妙的設計。

calc類型的rtype.tflag字段包含reflect.tflagUncommon標記,表示其類型信息中包含uncommonType數據。

uncommonType對象的大小是 16 字節,calc類型共有3個參數和返回值,3個類型指針占 24 個字節,所以 [mcount]method 相對uncommonType 對象的偏移是 16 + 24 = 40 字節。

通過計算得到如下結果:

calc類型的Ree方法,被重命名為main.calc.Ree,內存地址是0x00098240 + 0x401000 = 0x499240。它是一個導出函數,所以reflect.name.bytes[0] = 1。

calc類型的foo方法,被重命名為main.calc.foo,內存地址是0x000981e0 + 0x401000 = 0x4991e0。

從內存分析結果可以看到,如果一種數據類型定義了多個方法,而且有的是名稱以大寫字母開頭公共導出方法,有的是名稱以小寫字母開頭導私有方法,那么編譯器將公共的導出方法信息排序在前,私有方法信息排序在后,然后保存其數據類型信息中。而且這個結論可以在reflect/type.go源碼文件中定義的兩個方法得到印證:

  1. func (t *uncommonType) methods() []method { 
  2.   if t.mcount == 0 { 
  3.     return nil 
  4.   } 
  5.   return (*[1 << 16]method)(add(unsafe.Pointer(t), uintptr(t.moff), "t.mcount > 0"))[:t.mcount:t.mcount] 
  6.  
  7. func (t *uncommonType) exportedMethods() []method { 
  8.   if t.xcount == 0 { 
  9.     return nil 
  10.   } 
  11.   return (*[1 << 16]method)(add(unsafe.Pointer(t), uintptr(t.moff), "t.xcount > 0"))[:t.xcount:t.xcount] 

在本例中還可以看到,無論是Ree方法,還是foo方法,它們對應的method.mtyp字段值都是0xffffffff,也就是 -1。

從runtime/type.go源文件中resolveTypeOff函數的注釋可以了解到,-1表示沒有對應的類型信息。

也就是說,calc類型的Ree和foo方法雖然也是函數,但是他們沒有對應的函數類型信息。

所以,Go編譯器并沒有為每一個函數都生成對應的類型信息,只是在需要的時候才會生成,或者是運行時(runtime)根據需要生成。

匿名函數

代碼清單中,第三次調用main.Print函數輸出了一個匿名函數的類型信息。這個匿名函數沒有形成閉包,所以相對比較簡單。

將其內存數據整理成圖表如下:

該函數沒有參數、返回值、方法,所以其類型信息非常非常的簡單。相信已經不需要進一步介紹了。

總結

 

通過一步步的內存分析,對Go語言的函數進行了深入的了解,學習了很多知識,解開了許多疑惑,相信在實際開發中必定能游刃有余,避免一些小坑。

 

責任編輯:武曉燕 來源: Golang In Memory
相關推薦

2022-11-07 18:12:54

Go語言函數

2023-10-27 11:27:14

Go函數

2021-04-20 23:25:16

執行函數變量

2024-04-07 00:04:00

Go語言Map

2019-11-05 10:03:08

callback回調函數javascript

2025-01-13 13:00:00

Go網絡框架nbio

2019-08-19 12:50:00

Go垃圾回收前端

2016-12-08 15:36:59

HashMap數據結構hash函數

2020-07-21 08:26:08

SpringSecurity過濾器

2010-06-01 15:25:27

JavaCLASSPATH

2020-12-16 09:47:01

JavaScript箭頭函數開發

2010-06-28 10:12:01

PHP匿名函數

2009-11-18 12:38:04

PHP字符串函數

2021-12-28 17:39:05

Go精度Json

2023-10-19 11:12:15

Netty代碼

2009-09-25 09:14:35

Hibernate日志

2013-09-22 14:57:19

AtWood

2021-02-17 11:25:33

前端JavaScriptthis

2019-06-25 10:32:19

UDP編程通信

2017-08-15 13:05:58

Serverless架構開發運維
點贊
收藏

51CTO技術棧公眾號

在线综合亚洲欧美在线视频| 99久精品国产| 日韩在线观看免费高清| 欧美高清精品一区二区| 超碰在线免费播放| 成人18视频日本| 国产精国产精品| 中文字幕电影av| 秋霞影院一区二区三区| 欧美三级电影网站| www.日本少妇| a中文在线播放| 成人精品一区二区三区四区| 国产999精品久久久| 杨钰莹一级淫片aaaaaa播放| 黄色欧美网站| 91精品国产综合久久久蜜臀粉嫩| 欧美日韩黄色一级片| 9191在线| 久久精品夜色噜噜亚洲aⅴ| 亚洲一区二区日本| 国产精品传媒在线观看| 亚洲午夜一区| 久久天天躁夜夜躁狠狠躁2022| 国产一级伦理片| 精品入口麻豆88视频| 色久综合一二码| 久久久久久www| 国产日产一区二区三区| 久久免费国产精品| 高跟丝袜欧美一区| 日韩高清欧美高清| 在线视频日韩欧美| 日韩成人亚洲| 欧美日韩亚洲视频一区| 国产精品videossex国产高清 | 青椒成人免费视频| 久久久最新网址| 欧美成人手机视频| 国产高清久久| www.亚洲男人天堂| 国产精品久久久久久成人| 日本欧美韩国国产| 亚洲电影在线观看| 大桥未久恸哭の女教师| jazzjazz国产精品麻豆| 91麻豆精品久久久久蜜臀| 另类小说色综合| 外国电影一区二区| 欧美丝袜丝nylons| 91欧美视频在线| 久久精品资源| 欧美另类变人与禽xxxxx| 福利在线一区二区三区| 日韩中文影院| 欧美日韩五月天| 182午夜在线观看| 亚洲国产天堂| 日韩一区二区在线看| 黄色a级三级三级三级| 韩国女主播一区二区| 欧亚一区二区三区| 污片在线免费看| 午夜精品久久久内射近拍高清| 五月婷婷在线观看| 综合精品久久久| 亚洲小视频在线播放| 午夜伦理大片视频在线观看| 伊人一区二区三区| 免费不卡av在线| 999福利在线视频| 欧美性xxxx极品hd欧美风情| 男女av免费观看| 69堂精品视频在线播放| 欧美日韩大陆一区二区| 樱花草www在线| 极品国产人妖chinesets亚洲人妖| 精品久久国产字幕高潮| 国产精品久久久久久在线观看| 噜噜噜天天躁狠狠躁夜夜精品| 日韩精品中文字幕在线播放| 日韩一级av毛片| 91精品亚洲| 国产69精品99久久久久久宅男| 日韩 欧美 综合| 日日摸夜夜添夜夜添精品视频| 国产欧美日韩最新| 丁香六月天婷婷| 久久九九国产精品| 国产av不卡一区二区| theav精尽人亡av| 国产成人精品123区免费视频| 欧美性猛交xxxxxx富婆| 日韩精品xxx| 在线日韩网站| 欧美久久久精品| www.伊人久久| 国产一区二区0| 欧美日本韩国在线| 日本在线视频www鲁啊鲁| 色综合色狠狠天天综合色| 波多野结衣xxxx| 久久精品国产亚洲5555| 中文字幕少妇一区二区三区| 国产精品成人av久久| 青青青伊人色综合久久| 国产超碰91| 一区二区三区视频网站| 激情成人中文字幕| 99精品视频国产| 久久不见久久见免费视频7| 久久国产加勒比精品无码| 潘金莲一级淫片aaaaaa播放| 国产成人在线视频免费播放| 日韩精品久久久毛片一区二区| 色呦呦视频在线观看| 精品视频1区2区| 国产高清自拍视频| 韩国在线视频一区| 成人淫片在线看| 大片免费播放在线视频| 午夜精品久久久久| 亚洲一区二区三区三州| 1314成人网| 福利片在线一区二区| 神马国产精品影院av| 中文字幕第四页| 成人黄页毛片网站| 日韩一二区视频| 9999在线精品视频| 色香阁99久久精品久久久| 福利网址在线观看| 91小视频免费看| 日本手机在线视频| 福利在线一区| 午夜美女久久久久爽久久| 精品国产va久久久久久久| 国产精品网站一区| 91激情视频在线| 国产免费久久| 国产精品成人播放| 精品视频一二三| 色94色欧美sute亚洲13| 亚洲av无码一区二区三区网址 | 99久久久久免费精品国产| 日韩中文在线字幕| 久久69av| 欧美激情欧美激情| 欧美熟妇交换久久久久久分类| 亚洲精品乱码久久久久久| 91欧美一区二区三区| 66国产精品| 亚洲一区二区三区香蕉 | 2019中文字幕免费视频| 色一情一乱一区二区三区| 亚洲 欧美综合在线网络| 97人妻精品一区二区三区免费| 亚洲精品男同| 欧美高清视频一区| 日韩av超清在线观看| 国产一区二区三区在线播放免费观看| 国产一区免费看| 国产精品久久久久久久久动漫 | 又大又硬又爽免费视频| 精品视频在线你懂得| 国产91精品不卡视频| 国产原创av在线| 欧美高清性hdvideosex| 九九热视频精品| 99精品国产一区二区三区不卡| 极品粉嫩国产18尤物| 91精品国产自产精品男人的天堂 | 国产无遮挡又黄又爽在线观看| 成人av一区二区三区| heyzo亚洲| 成人a'v在线播放| 亚洲综合在线播放| 理论不卡电影大全神| 国产小视频国产精品| 国产精品嫩草影院精东| 亚洲国产一区二区三区| 成人午夜剧场视频网站| 久久99最新地址| 精品少妇在线视频| 精品精品久久| 成人h视频在线观看| 国产传媒av在线| 日韩中文第一页| 无码国产精品一区二区色情男同| 色94色欧美sute亚洲线路一ni| 亚洲国产精品免费在线观看| 91亚洲国产成人精品一区二区三| 国产无遮挡猛进猛出免费软件 | 国产一级特黄a大片免费| 91精品蜜臀一区二区三区在线| 精品久久久久久中文字幕动漫| 国产美女久久| 91精品国产免费久久久久久| 自拍视频在线免费观看| 亚洲国产精品久久久久| 中文字幕日日夜夜| 天天亚洲美女在线视频| tube国产麻豆| 欧美国产成人精品| 国产精品300页| 狠狠色综合日日| 久久久久久香蕉| 一区在线免费| 国产精品美女在线播放| 国产永久精品大片wwwapp| 成人在线视频电影| 99久久久成人国产精品| 国产成人精品电影久久久| 黄页网站大全在线免费观看| 色妞色视频一区二区三区四区| 四虎在线免费看| 亚洲а∨天堂久久精品喷水| 亚洲一区中文字幕在线| 色综合天天天天做夜夜夜夜做| 国产一级做a爰片在线看免费| 亚洲欧美综合另类在线卡通| 男人天堂av电影| 久久中文娱乐网| 亚洲黄色免费在线观看| 成人一区二区三区在线观看| 午夜一区二区视频| 毛片一区二区三区| 久久久久久三级| 天堂一区二区在线免费观看| 国产97在线 | 亚洲| 红桃视频亚洲| 日韩精品一区二区三区四 | 波多野结衣乳巨码无在线| 亚洲香蕉网站| 精品丰满人妻无套内射| 国产精品啊v在线| 国产小视频免费| 欧美精品日韩| 免费特级黄色片| 影音先锋国产精品| cao在线观看| 国产欧美成人| 国产男女在线观看| 久久久久久亚洲精品杨幂换脸| 免费在线激情视频| 另类国产ts人妖高潮视频| 能在线观看的av| 日韩国产精品久久久久久亚洲| 成人性视频欧美一区二区三区| 天堂影院一区二区| 日本人视频jizz页码69| 久久国产精品免费| 九九热视频免费| 成人一区二区在线观看| 波多野结衣影院| 久久亚洲精华国产精华液 | 深夜福利视频在线观看| 亚洲欧美在线磁力| 9i精品一二三区| 久久精品电影一区二区| av网址在线免费观看| 精品中文字幕在线观看| 97蜜桃久久| 国产成人精品a视频一区www| 欧美美女被草| 成人av播放| 欧美美女在线| 亚洲天堂av免费在线观看| 欧美色一级片| 无码精品国产一区二区三区免费| 免费视频一区二区| 中文字幕久久久久久久| av亚洲精华国产精华| 伊人网在线视频观看| 中文字幕亚洲欧美在线不卡| 青青草原国产视频| 一本大道综合伊人精品热热| 中文字幕第一页在线播放| 日韩三级视频中文字幕| 亚洲 欧美 激情 小说 另类| 中文字幕亚洲天堂| 久久亚洲导航| 国产成人精品免高潮费视频| 在线免费观看亚洲| 久久超碰亚洲| 婷婷综合亚洲| 丝袜老师办公室里做好紧好爽| 日本不卡视频一二三区| 岛国精品一区二区三区| 国产亚洲精品aa午夜观看| 国产97免费视频| 色女孩综合影院| 国产99999| 亚洲一区第一页| 免费在线看电影| 成人午夜国产| 日韩成人av网站| 欧美色图首页| 午夜剧场高清版免费观看| 成av人片一区二区| 777777国产7777777| 欧美性xxxx极品高清hd直播| 精品人妻无码一区二区三区蜜桃一| 亚洲毛片在线免费观看| 综合久久2o19| 国产女精品视频网站免费| 欧美电影完整版在线观看| 综合色婷婷一区二区亚洲欧美国产| 夜久久久久久| 久久久国产精品久久久| 日本一区二区免费在线观看视频| 亚洲国产精品成人无久久精品| 欧美麻豆精品久久久久久| 青青青草网站免费视频在线观看| 九九精品在线视频| 日本在线一区二区| 欧美日韩精品免费观看视一区二区| 欧美精品国产| 免费精品99久久国产综合精品应用| 91色在线porny| 国产无套在线观看| 日韩精品一区二区三区视频播放 | 午夜视频免费在线| 美女福利视频一区| 亚洲欧美一级| 亚洲图片小说在线| 奇米888四色在线精品| 精品黑人一区二区三区观看时间| 亚洲在线视频网站| a在线观看免费| 久久夜色精品国产欧美乱| 成人18视频在线观看| 日韩精品久久久免费观看| 久久综合激情| 日本黄色网址大全| 欧美日韩在线一区| 日本一级在线观看| 青青在线视频一区二区三区| 日本午夜精品| 日本三级免费观看| 久久综合九色综合97_久久久| 国产精品100| 亚洲精品一区二区三区婷婷月| 国产网站在线| 久久一区二区精品| 老司机午夜精品视频| 亚洲国产精品电影| 一卡二卡三卡在线观看| 日韩中文在线视频| 91麻豆精品一二三区在线| 中文字幕一区二区三区5566| 精品综合免费视频观看| 老司机成人免费视频| 91精品国产福利在线观看| 中文字幕中文字幕在线中高清免费版 | 久久99精品久久久久久久久久久久| www久久久久久久| 欧美精品在线视频| 91一区二区三区在线| 成人免费视频网站| 精品91在线| 亚洲一区二区三区蜜桃| 欧美亚洲自拍偷拍| 久cao在线| 国产99在线免费| 亚洲综合国产激情另类一区| 91国模少妇一区二区三区| 欧美日韩国产小视频在线观看| 国精产品一区| 国产一区二区久久久| 久久精品亚洲一区二区| 久久一级免费视频| 欧美成人官网二区| 网友自拍亚洲| 吴梦梦av在线| av一二三不卡影片| 中文资源在线播放| 欧美肥老妇视频| 嫩草影视亚洲| 亚洲色图欧美自拍| 黄色一区二区在线观看| 日本三级在线视频| 国产精华一区| 毛片不卡一区二区| 国产精品美女毛片真酒店| 中文一区二区视频| 超碰在线亚洲| 超碰在线公开97| 亚洲高清免费视频| 日本黄色片在线观看| 精品一区2区三区| 精品亚洲国产成人av制服丝袜| 日本最新中文字幕| 久久影视电视剧免费网站| 久久精品国产亚洲5555| 午夜不卡福利视频| 色婷婷激情综合| 91九色在线看| 自拍视频一区二区三区| 久久久久久免费网|