go并發(fā)協(xié)程-通道channel

1.什么是Channel?

channelGo的通道潦嘶,是協(xié)程之間的通信機(jī)制榛丢。一個(gè)channel是一條通信管道卡辰,它可以讓一個(gè)協(xié)程通過它給另一個(gè)協(xié)程發(fā)送數(shù)據(jù)。每個(gè)channel都需要指定數(shù)據(jù)類型,即channel可發(fā)送數(shù)據(jù)的類型族沃。Go語言主張通過數(shù)據(jù)傳遞來實(shí)現(xiàn)共享內(nèi)存误辑,而不是通過共享內(nèi)存來實(shí)現(xiàn)數(shù)據(jù)傳遞。

2. 創(chuàng)建Channel

2.1 語法

channel是引用類型尤泽,需要使用make()進(jìn)行創(chuàng)建欣簇。

// 聲明方式1
var cha1 chan 數(shù)據(jù)類型 
cha1 = make(chan 數(shù)據(jù)類型)

// 聲明方式2
cha1 := make(chan 數(shù)據(jù)類型)

2.2 使用示例

package main
import (
    "fmt"
)
type People struct {}
func main() {
    // 創(chuàng)建一個(gè)整數(shù)型chan
    intChan := make(chan int)
    fmt.Printf("intChan類型: %T 值: %v \n",intChan,intChan)
    // 創(chuàng)建一個(gè)空接口chan,可以存放任意類型數(shù)據(jù)
    interfaceChan := make(chan interface{})
    fmt.Printf("interfaceChan類型: %T 值: %v \n",interfaceChan,interfaceChan)
    // 創(chuàng)建一個(gè)指針chan
    peopleChan := make(chan *People)
    fmt.Printf("peopleChan類型: %T 值: %v \n",peopleChan,peopleChan)
}
/** 輸出
 intChan類型: chan int 值: 0xc000052060 
 interfaceChan類型: chan interface {} 值: 0xc0000520c0 
 peopleChan類型: chan *main.People 值: 0xc000052120 
*/

3.發(fā)送數(shù)據(jù)

3.1 語法

通過channel發(fā)送數(shù)據(jù)需要使用特殊的操作符<-,需要注意的是: channel發(fā)送的值的類型必須與channel的元素類型一致坯约。

channel變量名 <- 值

3.2 錯(cuò)誤使用示例

package main
import (
    "fmt"
    "time"
)
type People struct {
}
func main() {
    // 創(chuàng)建一個(gè)整數(shù)型chan
    intChan := make(chan int)
    // 寫入
    intChan <- 5
  fmt.Printf("intChan類型: %T 值: %v \n", intChan, intChan)
}

上面示例運(yùn)行會(huì)死鎖熊咽,報(bào)錯(cuò)內(nèi)容如下:

fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.main()
        /Users/hui/Project/Go/src/go-basic/main.go:12 +0x59
Process finished with exit code 2

報(bào)錯(cuò)原因: 如果Goroutine在一個(gè)channel上發(fā)送數(shù)據(jù),其他的Goroutine應(yīng)該接收得到數(shù)據(jù)鬼店;如果沒有接收网棍,那么程序?qū)⒃谶\(yùn)行時(shí)出現(xiàn)死鎖。

3.3 正確使用示例

package main
import (
    "fmt"
)
func main() {
    // 創(chuàng)建一個(gè)整數(shù)型chan
    intChan := make(chan int)
    // 寫入數(shù)據(jù)(協(xié)程寫入)
    go sendMsg(intChan)
    // 接收數(shù)據(jù)(主線程讀取)
    a := <- intChan
    fmt.Printf("接收數(shù)據(jù): %v \n", a)
    fmt.Println("運(yùn)行結(jié)束! ")
}
func sendMsg(intChan chan int ){
    // 寫入
    intChan <- 5
    fmt.Println("寫入數(shù)據(jù): 5 ")
}
/** 輸出:
  寫入數(shù)據(jù): 5 
  接收數(shù)據(jù): 5 
  運(yùn)行結(jié)束! 
*/

4.普通接收

channel接收同樣使用特殊的操作符<-妇智。

4.1 阻塞接收語法

// 方式一: ch 指的是通道變量
data := <- ch
//方式二: data 表示接收到的數(shù)據(jù)滥玷。未接收到數(shù)據(jù)時(shí),data為channel類型的零值巍棱,ok(布爾類型)表示是否接收到數(shù)據(jù)
data,ok := <- ch

執(zhí)行該語句時(shí)channel將會(huì)阻塞惑畴,直到接收到數(shù)據(jù)并賦值給data變量。

4.2 忽略接收語法

<- ch

執(zhí)行該語句時(shí)channel將會(huì)阻塞航徙。其目的不在于接收channel中數(shù)據(jù)如贷,而是為了阻塞Goroutine

如果Goroutine正在等待從channel接收數(shù)據(jù)到踏,而其他Goroutine并沒有寫入數(shù)據(jù)時(shí)程序?qū)?huì)死鎖杠袱。

5. 循環(huán)接收

循環(huán)接收數(shù)據(jù),需要配合使用關(guān)閉channel窝稿,借助普通for循環(huán)和for ... range語句循環(huán)接收多個(gè)元素楣富。遍歷channel,遍歷的結(jié)果就是接收到的數(shù)據(jù)伴榔,數(shù)據(jù)類型就是channel的數(shù)據(jù)類型纹蝴。普通for循環(huán)接收channel數(shù)據(jù)庄萎,需要有break循環(huán)的條件;for … range會(huì)自動(dòng)判斷出channel已關(guān)閉塘安,而無須通過判斷來終止循環(huán)糠涛。

5.1 使用普通for接收

方式一: data := <- ch

package main
import "fmt"
func main() {
    // 創(chuàng)建一個(gè)整數(shù)型chan
    intChan := make(chan int)
    // 寫入數(shù)據(jù)(協(xié)程寫入)
    go func(cha chan int) {
        // 寫入
        for i := 1; i < 5; i++ {
            intChan <- i
            fmt.Printf("寫入數(shù)據(jù) ->  %v \n", i)
        }
        // 關(guān)閉通道
        close(intChan)
    }(intChan)

    // 方式一: data := <- ch
    for {
        // 接收數(shù)據(jù)
        out := <-intChan
        // 判斷通道是否關(guān)閉
        //如果通道關(guān)閉,則out為通道類型的零值兼犯,這里是int型忍捡,所以是0
        if out == 0 {
            fmt.Println("通道已關(guān)閉")
            break
        }
        fmt.Printf("接收數(shù)據(jù) ==> %v \n", out)
    }
    fmt.Println("程序運(yùn)行結(jié)束!")
}
/** 輸出:
  寫入數(shù)據(jù) ->  1 
  接收數(shù)據(jù) ==> 1 
  接收數(shù)據(jù) ==> 2 
  寫入數(shù)據(jù) ->  2 
  寫入數(shù)據(jù) ->  3 
  接收數(shù)據(jù) ==> 3 
  接收數(shù)據(jù) ==> 4 
  寫入數(shù)據(jù) ->  4 
  通道已關(guān)閉
  程序運(yùn)行結(jié)束!
*/

方式二: data,ok := <- ch

package main
import "fmt"
func main() {
    // 創(chuàng)建一個(gè)整數(shù)型chan
    intChan := make(chan int)
    // 寫入數(shù)據(jù)(協(xié)程寫入)
    go func(cha chan int) {
        // 寫入
        for i := 1; i < 5; i++ {
            intChan <- i
            fmt.Printf("寫入數(shù)據(jù) ->  %v \n", i)
        }
        // 關(guān)閉通道
        close(intChan)
    }(intChan)

    // 方式二: data,ok := <- ch
    for {
        // 接收數(shù)據(jù)
        out,ok := <-intChan
        // 判斷通道是否關(guān)閉,如果通道關(guān)閉,則ok為false
        if !ok {
            fmt.Println("通道已關(guān)閉")
            break
        }
        fmt.Printf("接收數(shù)據(jù) ==> %v \n", out)
    }
    fmt.Println("程序運(yùn)行結(jié)束!")
}
/** 輸出:
  寫入數(shù)據(jù) ->  1 
  接收數(shù)據(jù) ==> 1 
  接收數(shù)據(jù) ==> 2 
  寫入數(shù)據(jù) ->  2 
  寫入數(shù)據(jù) ->  3 
  接收數(shù)據(jù) ==> 3 
  接收數(shù)據(jù) ==> 4 
  寫入數(shù)據(jù) ->  4 
  通道已關(guān)閉
  程序運(yùn)行結(jié)束!
*/

5.2 使用for...range接收

package main
import "fmt"
func main() {
    // 創(chuàng)建一個(gè)整數(shù)型chan
    intChan := make(chan int)
    // 寫入數(shù)據(jù)(協(xié)程寫入)
    go func(cha chan int) {
        // 寫入
        for i := 1; i < 5; i++ {
            intChan <- i
            fmt.Printf("寫入數(shù)據(jù) ->  %v \n", i)
        }
        // 關(guān)閉通道
        close(intChan)
    }(intChan)
    // 使用 for...range接收
    for data := range intChan {
        fmt.Printf("接收數(shù)據(jù) ==> %v \n", data)
    }
    fmt.Println("程序運(yùn)行結(jié)束!")
}
/** 輸出:
  寫入數(shù)據(jù) ->  1 
  接收數(shù)據(jù) ==> 1 
  接收數(shù)據(jù) ==> 2 
  寫入數(shù)據(jù) ->  2 
  寫入數(shù)據(jù) ->  3 
  接收數(shù)據(jù) ==> 3 
  接收數(shù)據(jù) ==> 4 
  寫入數(shù)據(jù) ->  4 
  程序運(yùn)行結(jié)束!
*/

6. Channle的阻塞特性

6.1 特性如下

  • channel默認(rèn)是阻塞的免都。
  • 當(dāng)數(shù)據(jù)被發(fā)送到channel時(shí)會(huì)發(fā)生阻塞锉罐,直到有其他Goroutine從該channel中讀取數(shù)據(jù)。
  • 當(dāng)從channel讀取數(shù)據(jù)時(shí)绕娘,讀取也會(huì)被阻塞脓规,直到其他Goroutine將數(shù)據(jù)寫入該channel

6.2 特性使用

package main
import "fmt"
func main() {
    // 創(chuàng)建一個(gè)整數(shù)型chan
    intChan := make(chan int)
    // 創(chuàng)建一個(gè)用于阻塞的chan
    boolChan := make(chan bool)

    // 創(chuàng)建一個(gè)寫入數(shù)據(jù)的協(xié)程
    go func(cha chan int) {
        // 寫入
        intChan <- 50
        fmt.Println("寫入數(shù)據(jù)50")
        // 關(guān)閉通道
        close(intChan)
    }(intChan)

    // 創(chuàng)建一個(gè)讀取數(shù)據(jù)的協(xié)程
    go func(intChan chan int, boolChan chan  bool) {
        data,ok := <- intChan
        if ok {
            fmt.Printf("讀取到數(shù)據(jù) ->  %v \n", data)
            // 讀取到數(shù)據(jù)后险领,給boolChan寫入值
            boolChan <- true
            // 關(guān)閉用于的阻塞的chan
            close(boolChan)
        }
    }(intChan,boolChan)
    // 忽略接收侨舆,達(dá)到阻塞的效果。(如果不阻塞绢陌,則會(huì)直接輸出: 程序運(yùn)行結(jié)束!,不會(huì)等待協(xié)程執(zhí)行)
    <- boolChan
    fmt.Println("程序運(yùn)行結(jié)束!")
}
/** 輸出
  寫入數(shù)據(jù)50
  讀取到數(shù)據(jù) ->  50 
  程序運(yùn)行結(jié)束!
*/

阻塞channel等待匿名函數(shù)的Goroutine運(yùn)行結(jié)束挨下,防止主函數(shù)的Goroutine退出而導(dǎo)致匿名函數(shù)的Goroutine提前退出。

7.關(guān)閉Channel

發(fā)送方寫入完畢后需要主動(dòng)關(guān)閉channel脐湾,用于通知接收方數(shù)據(jù)傳遞完畢臭笆。接收方通過data,ok := <- ch判斷channel是否關(guān)閉,如果ok=false秤掌,則表示channel已經(jīng)被關(guān)閉愁铺。

7.1 使用示例

package main
import "fmt"
func main() {
    // 創(chuàng)建一個(gè)整數(shù)型chan
    intChan := make(chan int)
    // 創(chuàng)建一個(gè)寫入channel的協(xié)程
    go func(intChan chan int) {
        intChan <- 10
        intChan <- 20
        // 關(guān)閉通道
        close(intChan)
    }(intChan)

    // 讀取數(shù)據(jù)
    a := <- intChan
    fmt.Printf("接收數(shù)據(jù): %v \n",a)
    b := <- intChan
    fmt.Printf("接收數(shù)據(jù): %v \n",b)

    // 此時(shí)的Chan已經(jīng)關(guān)閉,而且里面的數(shù)據(jù)也都已經(jīng)取完
    c := <- intChan
    fmt.Printf("接收數(shù)據(jù): %v \n",c)
    fmt.Println("程序運(yùn)行結(jié)束!")
}
/** 輸出
  接收數(shù)據(jù): 10 
  接收數(shù)據(jù): 20 
  接收數(shù)據(jù): 0 
  程序運(yùn)行結(jié)束!
*/

又上面示例可以看出: 可以從關(guān)閉后的channel中繼續(xù)讀取數(shù)據(jù)闻鉴,取到的值為該類型的零值茵乱。比如整型是:0; 字符串是:""

7.2 向已關(guān)閉的chan寫入數(shù)據(jù),會(huì)崩潰

往關(guān)閉的channel中寫入數(shù)據(jù)會(huì)報(bào)錯(cuò):panic: send on closed channel。導(dǎo)致程序崩潰孟岛。

package main
import "fmt"
func main() {
    // 創(chuàng)建一個(gè)整數(shù)型chan
    intChan := make(chan int)
    // 創(chuàng)建一個(gè)寫入channel的協(xié)程
    go func(intChan chan int) {
        intChan <- 10
        // 關(guān)閉通道
        close(intChan)
    // 向已關(guān)閉的chan 繼續(xù)寫入數(shù)據(jù)瓶竭,會(huì)報(bào)錯(cuò);
        intChan <- 20
    }(intChan)
    // 讀取數(shù)據(jù)
    a := <- intChan
    fmt.Printf("接收數(shù)據(jù): %v \n",a)
    b := <- intChan
    fmt.Printf("接收數(shù)據(jù): %v \n",b)
    fmt.Println("程序運(yùn)行結(jié)束!")
}
/** 輸出:
接收數(shù)據(jù): 10 
接收數(shù)據(jù): 0 
panic: send on closed channel

goroutine 18 [running]:
main.main.func1(0xc000100060)
        /Users/hui/Project/Go/src/go-basic/main.go:14 +0x5f
created by main.main
        /Users/hui/Project/Go/src/go-basic/main.go:10 +0x6a

Process finished with exit code 2
*/

7.3 重復(fù)關(guān)閉chan,會(huì)崩潰

package main]
import "fmt"
func main() {
    // 創(chuàng)建一個(gè)整數(shù)型chan
    intChan := make(chan int)

    // 創(chuàng)建一個(gè)寫入channel的協(xié)程
    go func(intChan chan int) {
        intChan <- 10
        // 關(guān)閉通道
        close(intChan)
    }(intChan)

    // 讀取數(shù)據(jù)
    a := <- intChan
    fmt.Printf("接收數(shù)據(jù): %v \n",a)
    b := <- intChan
    fmt.Printf("接收數(shù)據(jù): %v \n",b)
    // 重復(fù)關(guān)閉(此處會(huì)報(bào)錯(cuò))
    close(intChan)
    fmt.Println("程序運(yùn)行結(jié)束!")
}
/** 輸出
接收數(shù)據(jù): 10 
接收數(shù)據(jù): 0 
panic: close of closed channel

goroutine 1 [running]:
main.main()
        /Users/hui/Project/Go/src/go-basic/main.go:22 +0x1cc

Process finished with exit code 2
*/

8.緩沖Channel

默認(rèn)創(chuàng)建的都是非緩沖channel渠羞,讀寫都是即時(shí)阻塞怨规。緩沖channel自帶一塊緩沖區(qū)芥吟,可以暫時(shí)存儲(chǔ)數(shù)據(jù)兔仰,如果緩沖區(qū)滿了胜卤,就會(huì)發(fā)生阻塞浸间。緩沖通道在發(fā)送時(shí)無需等待接收方接收即可完成發(fā)送過程玩徊,并且不會(huì)發(fā)生阻塞僧叉,只有當(dāng)緩沖區(qū)滿時(shí)才會(huì)發(fā)生阻塞拌滋。同理,如果緩沖通道中有數(shù)據(jù)雌芽,接收時(shí)將不會(huì)發(fā)生阻塞授艰,直到通道中沒有數(shù)據(jù)可讀時(shí),通道將會(huì)再度阻塞世落。

8.1 語法

// 聲明 n:代表緩沖區(qū)大小
cha1 := make(chan T,n)

8.2 使用示例

package main
import (
    "fmt"
    "time"
)
func main() {
    fmt.Printf("開始時(shí)間: %v \n",time.Now().Unix())
    // 創(chuàng)建一個(gè)緩沖區(qū)為2的整數(shù)型chan
    intChan2 := make(chan int,2)
    // 不會(huì)發(fā)生阻塞淮腾,因?yàn)榫彌_區(qū)未滿
    intChan2 <- 100
    fmt.Printf("結(jié)束時(shí)間: %v \n",time.Now().Unix())
    fmt.Printf("intChan2  類型: %T 緩沖大小: %v \n",intChan2,cap(intChan2))
    fmt.Println("程序運(yùn)行結(jié)束!")
}
/**輸出:
  開始時(shí)間: 1607496281 
  結(jié)束時(shí)間: 1607496281 
  intChan2  類型: chan int 緩沖大小: 2 
  程序運(yùn)行結(jié)束!
*/

9.單向Channel

channel默認(rèn)都是雙向的,即可讀可寫屉佳。定向channel也叫單向channel谷朝,只讀或只寫。直接創(chuàng)建單向channel沒有任何意義武花。通常的做法是創(chuàng)建雙向channel圆凰,然后以單向channel的方式進(jìn)行函數(shù)傳遞。

9.1 介紹

// 只讀
ch <- chan T
// 只寫
ch chan <- T

9.1 使用

package main
import (
    "fmt"
    "time"
)
func main() {
    // 創(chuàng)建一個(gè)整數(shù)型chan
    intChan := make(chan int)
    go writeChan(intChan)
    go readChan(intChan)
    time.Sleep(50 * time.Millisecond)
    fmt.Println("運(yùn)行結(jié)束")

}

// 定義只讀通道的函數(shù)
func readChan( ch <- chan int)  {
    for data := range ch {
        fmt.Printf("讀出數(shù)據(jù): %v \n",data)
    }
}
// 定義只寫通道的函數(shù)
func writeChan( ch chan <- int){
    for i:= 1; i< 5 ; i++ {
        ch <- i
        fmt.Printf("寫入數(shù)據(jù): %v \n",i)
    }
    close(ch)
}

10.計(jì)時(shí)器與channel

計(jì)時(shí)器類型表示單個(gè)事件体箕。當(dāng)計(jì)時(shí)器過期時(shí)专钉,當(dāng)前時(shí)間將被發(fā)送到c上(c是一個(gè)只讀channel <-chan time.Time,該channel中放入的是Timer結(jié)構(gòu)體)累铅,除非計(jì)時(shí)器是After()創(chuàng)建的跃须。計(jì)時(shí)器必須使用NewTimer()After()創(chuàng)建。

10.1 NewTimer

NewTimer()創(chuàng)建一個(gè)新的計(jì)時(shí)器娃兽,它會(huì)在至少持續(xù)時(shí)間d之后將當(dāng)前時(shí)間發(fā)送到其channel上菇民。

使用示例:

package main
import (
    "fmt"
    "time"
)
func main() {
    // 創(chuàng)建一個(gè)計(jì)時(shí)器
    timer := time.NewTimer(5 * time.Second)
    fmt.Printf("開始時(shí)間 %v \n",time.Now())
    // 此處會(huì)阻塞5秒
    out := <- timer.C
    fmt.Printf("變量out->  類型: %T 值:%v  \n",out,out)
    fmt.Printf("開始時(shí)間 %v \n",time.Now())
}
/** 輸出:
  開始時(shí)間 2020-12-10 10:53:22.979673 +0800 CST m=+0.000174275 
  變量out->  類型: time.Time 值:2020-12-10 10:53:27.980079 +0800 CST m=+5.000489969  
  開始時(shí)間 2020-12-10 10:53:27.980264 +0800 CST m=+5.000674880 
*/

10.2 After

After()函數(shù)相當(dāng)于NewTimer(d). C,如下源碼:

func After(d Duration) <-chan Time {
    return NewTimer(d).C
}

使用示例

package main
import (
    "fmt"
    "time"
)
func main() {
    // 創(chuàng)建一個(gè)計(jì)時(shí)器,返回的是chan
    ch := time.After(5 * time.Second)
    fmt.Printf("開始時(shí)間 %v \n",time.Now())
    // 此處會(huì)阻塞5秒
    out := <- ch
    fmt.Printf("變量out->  類型: %T 值:%v  \n",out,out)
    fmt.Printf("開始時(shí)間 %v \n",time.Now())
}
/** 輸出
  開始時(shí)間 2020-12-10 11:01:07.272154 +0800 CST m=+0.000153152 
  變量out->  類型: time.Time 值:2020-12-10 11:01:12.273034 +0800 CST m=+5.000956630  
  開始時(shí)間 2020-12-10 11:01:12.273153 +0800 CST m=+5.001076196 
*/
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市投储,隨后出現(xiàn)的幾起案子第练,更是在濱河造成了極大的恐慌,老刑警劉巖轻要,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件复旬,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡冲泥,警方通過查閱死者的電腦和手機(jī)驹碍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來凡恍,“玉大人志秃,你說我怎么就攤上這事〗涝停” “怎么了浮还?”我有些...
    開封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長闽巩。 經(jīng)常有香客問我钧舌,道長担汤,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任洼冻,我火速辦了婚禮崭歧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘撞牢。我一直安慰自己率碾,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開白布屋彪。 她就那樣靜靜地躺著所宰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪畜挥。 梳的紋絲不亂的頭發(fā)上仔粥,一...
    開封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音砰嘁,去河邊找鬼件炉。 笑死,一個(gè)胖子當(dāng)著我的面吹牛矮湘,可吹牛的內(nèi)容都是我干的斟冕。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼缅阳,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼磕蛇!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起十办,我...
    開封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤秀撇,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后向族,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體呵燕,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年件相,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了再扭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡夜矗,死狀恐怖泛范,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情紊撕,我是刑警寧澤罢荡,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響区赵,放射性物質(zhì)發(fā)生泄漏惭缰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一笼才、第九天 我趴在偏房一處隱蔽的房頂上張望从媚。 院中可真熱鬧,春花似錦患整、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至到千,卻和暖如春昌渤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背憔四。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來泰國打工膀息, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人了赵。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓潜支,卻偏偏與公主長得像,于是被迫代替她去往敵國和親柿汛。 傳聞我的和親對(duì)象是個(gè)殘疾皇子冗酿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容