Go學(xué)習(xí)

《Go語言編程》 許式偉 呂桂華 著

一腮敌、語言特性

垃圾回收阱当、更豐富內(nèi)置類型、函數(shù)多返回值糜工、錯誤處理弊添、匿名函數(shù)和閉包、類型和接口捌木、并發(fā)編程油坝、反射、語言交互性

二、順序編程


2.2 常量

  • 如果定義常量時沒有指定類型澈圈,那么它與字面量一樣彬檀,是無類型常量。
const(
  size int 64 = 1024
  eof = -1
)
  • iota 在每個const關(guān)鍵詞出現(xiàn)時被重置為0瞬女,然后沒出現(xiàn)一次iota窍帝,其所代表數(shù)字會增加1
const(
  c0 = iota    //c0 == 0
  c1               //c1==1
  c2              //c2==2
)
  • 枚舉:
    Go不支持明確的enum關(guān)鍵字。
    下面是一個常規(guī)的枚舉表示法:
const(
Sunday = iota
Monday
Tuesday
Wednesday
...
)

以大寫字母開頭的常量在包外可見

2.3類型

對于常規(guī)開發(fā)來說诽偷,用int和uint就可以了坤学,以免導(dǎo)致移植困難
字符串在Go中也是基本類型,字符串的內(nèi)容不能在初始化后被修改

  • 字符串遍歷:
str := "hello world"
n := len(str)
for i:=0; i<n; i++{
  ch := str[i]
  fmt.Println(ch)
}
for _,v := range myArray{
  fmt.Print(v)
}
  • 字符類型
    Go中支持兩個字符類型报慕,一個是Byte深浮,一個是rune

  • 數(shù)組
    在Go中,數(shù)組是值類型眠冈,所有的值類型變量在賦值和作為參數(shù)傳遞時都將產(chǎn)生一次復(fù)制動作飞苇。若數(shù)組作為函數(shù)的參數(shù)類型,則在調(diào)用時函數(shù)體中無法修改傳入數(shù)組的內(nèi)容洋闽。若想修改玄柠,需使用切片來實現(xiàn)。

  • 切片
    類似于C++中數(shù)組和vector的關(guān)系诫舅。
    基于數(shù)組創(chuàng)建切片:

var myArray [10]int = [10]int{1,2,3,4,5,6,7,8,9,10}
var mySlice []int = myArray[:5]
#遍歷切片
for _, v := range mySlice{
  fmt.Print(v)
}

直接創(chuàng)建:

mySlice := make([]int, 5) //初始元素個數(shù)為5的切片羽利,初始值為0
mySlice := make([]int, 5, 10) //初始元素個數(shù)為5的切片,初始值為0刊懈,并預(yù)留10個元素的存儲空間
mySlice := []int{1,2,3,4,5}

在切片后附加元素:

mySlice = append(mySlice, 1, 2, 3) //附加1这弧,2,3
mySlice = append(mySlice, mySlice...) //...相當于把mySlice打散了傳進去

內(nèi)容復(fù)制:
copy() :若兩個切片不一樣虚汛,就會按較小的那個數(shù)組切片的元素個數(shù)進行復(fù)制

  • map
    GO中map也是基本數(shù)據(jù)類型
#聲明
var myMap map[string] PersonInfo   //PersonInfo是一個結(jié)構(gòu)體匾浪,也是value的類型
#創(chuàng)建
myMap = make(map[string] PersonInfo)
# 賦值
myMap["1234"] = PersonInfo{初始化}
# 刪除
delete(myMap,"1234")
#查找
value, ok := myMap["1234"]
if ok{
  處理value
}

2.4流程控制語句

  • 跳轉(zhuǎn)語句
    goto 標簽

2.5函數(shù)

小寫字母開頭的函數(shù)只在包內(nèi)可見,大寫字母開頭的函數(shù)才能被其他包使用(前提是在導(dǎo)入了包的情況下)

func Add(a int, b int) (ret int, err error){
   if a<0 || b<0 {
      err = errors.New("error")
      return  //在函數(shù)中執(zhí)行不帶任何參數(shù)的return語句時卷哩,會返回對應(yīng)的返回值變量的值
  }
   return a+b, nil
}
  • 不定參數(shù)
func myFun(args ...int){
  for _, v := range args{
    fmt.Print(v)
  }
}

不定參數(shù)的傳遞:

myfun(args...)
myfun(args[1:]...)  //任意的int slice都可以傳進去

任意類型不定參數(shù)的傳遞:

func Printf(format string, args ...interface{}){
    //...
}

用interface{}傳遞任意類型數(shù)據(jù)是GO語言的慣例用法

  • 匿名函數(shù)和閉包
    在Go中蛋辈,函數(shù)可以像普通變量一樣被傳遞或使用
    匿名函數(shù)可以直接賦值給一個變量或者直接執(zhí)行
    閉包可以非常靈活地操作外部變量,因此在Go語言中将谊,閉包常用于創(chuàng)建函數(shù)變量冷溶、實現(xiàn)函數(shù)式編程、并發(fā)編程等場景尊浓。

2.6 錯誤處理

  • error接口
type error interface{
  Error() string
}

對于大多數(shù)函數(shù)逞频,若要返回錯誤,可定義為如下模式:
將error作為返回值的最后一個

func Foo(param int) (n int, err error){}

#調(diào)用代碼時:
n, err := Foo(0)

if err != nil{
  // 錯誤處理
} else {
   // 使用返回值n
}
  • 定義自己的error類型
    首先栋齿,定義一個用于承載錯誤信息的類型
type PathError struct {
  Op string
  Path string
  Err error
}

然后苗胀,實現(xiàn)Error()方法

func (e *PathError) Error() string{
  return e.Op + "" + e.Path + "" + e.Err.Error()
}

返回err時襟诸,只需要將其他函數(shù)返回的普通的err當作參數(shù)用于初始化PathError,然后就可以直接返回PathError變量了基协。

  • defer
    在當前函數(shù)退出前執(zhí)行defer的操作歌亲,defer遵循先進后出的原則
defer srcFile.Close()
# 可以加一個匿名函數(shù)處理
defer func(){
}()  
  • panic() 和 recover()
    報告和處理運行時錯誤和程序中的錯誤場景

panic 用于引發(fā)運行時錯誤”ぬ停可以調(diào)用 panic 函數(shù)來中止程序的正常執(zhí)行应结。panic 會導(dǎo)致程序立即停止,并觸發(fā)執(zhí)行函數(shù)調(diào)用棧的逆序執(zhí)行泉唁,直到所有被推遲(defer)的函數(shù)調(diào)用執(zhí)行完畢鹅龄,然后程序退出。

recover 用于捕獲 panic 引發(fā)的異常亭畜,并在程序中恢復(fù)扮休。它只能在延遲函數(shù)中調(diào)用,用于恢復(fù) panic 引發(fā)的錯誤拴鸵。

三玷坠、面向?qū)ο缶幊?/h2>

3.1類型系統(tǒng)

  • 為類型添加方法
    Go語言中的大多數(shù)類型都是值語義【⒚辏可以給任何類型八堡,包括內(nèi)置類型增加新方法。任何類型都可以被Any類型引用聘芜,Any類型就是空接口兄渺,即interface{}

通過為int取別名并增加了方法,他就變成了一個全新的類型汰现,但這個新類型又完全擁有int的功能:

type Integer int
func (a Integer) Less(b Integer) bool {
  return a<b
}

只有在需要修改對象的時候挂谍,才必須使用指針

func (a *Integer) Add (b Integer){
  *a += b
}
  • 值語義和引用語義
    GO中數(shù)組切片,map瞎饲,channel口叙,接口是引用語義

  • 結(jié)構(gòu)體
    Go的結(jié)構(gòu)體和其他語言的類具有同等地位。因為所有的Go語言類型(指針除外)都可以有自己的方法嗅战,所以妄田,結(jié)構(gòu)體只是很普通的符合類型。

3.2 初始化

rectPtr := new(Rect)  //使用new關(guān)鍵字創(chuàng)建結(jié)構(gòu)體指針
rect2 := &Rect{}  //也是指針驮捍,加了&的都是指針疟呐,不加&就直接返回對象
rect3 := &Rect{0,0,100,200}
rect4 := &Rect{width:100, height:200}

在Go中無構(gòu)造函數(shù)的概念,對象的創(chuàng)建通常交由一個全局的創(chuàng)建函數(shù)來完成厌漂,以NewXXX來命名

func NewRect(x,y,width,height float64) *Rect{
  return &Rect{x,y,width,height}
}

3.3匿名組合

Go也提供了繼承,但采用了組合的文法斟珊,所以將其稱為匿名組合苇倡。

// 定義一個Person結(jié)構(gòu)體
type Person struct {
    Name string
    Age  int
}

// 定義一個Student結(jié)構(gòu)體富纸,匿名組合了Person結(jié)構(gòu)體
type Student struct {
    Person
    Grade int
}

func main() {
    // 創(chuàng)建一個Student對象
    student := Student{
        Person: Person{
            Name: "Alice",
            Age:  20,
        },
        Grade: 10,
    }

    // 訪問Student對象的字段
    fmt.Println("Name:", student.Name) // 輸出: Name: Alice
    fmt.Println("Age:", student.Age)   // 輸出: Age: 20
    fmt.Println("Grade:", student.Grade) // 輸出: Grade: 10
}
//Student 結(jié)構(gòu)體匿名組合了 Person 結(jié)構(gòu)體。這意味著 Student 類型繼承了 Person 類型的所有字段和方法旨椒。
  • 方法重寫
    當結(jié)構(gòu)體通過匿名組合嵌套了多個結(jié)構(gòu)體晓褪,且這些結(jié)構(gòu)體有相同方法名時,可進實現(xiàn)重寫效果

3.5 接口

在Go語言中综慎,一個類只需要實現(xiàn)了接口要求的所有函數(shù)涣仿,我們就說這個類實現(xiàn)了該接口

3.5.3 接口賦值

有兩種情況:將對象實例賦值給接口(賦值時對象前加&)、將一個接口賦值給另外一個接口(方法列表為其子集)

3.5.4接口查詢

接口查詢是指通過類型斷言或類型判斷來判斷一個值是否實現(xiàn)了特定的接口示惊,并獲取其實現(xiàn)的接口類型或調(diào)用接口方法好港。

  • 類型斷言
    類型斷言用于將一個接口類型的值轉(zhuǎn)換為其他具體類型。如果轉(zhuǎn)換成功米罚,可以訪問其特定類型的方法和屬性钧汹。
type Shape interface {
    Area() float64
}

type Circle struct {
    Radius float64
}

func (c Circle) Area() float64 {
    return 3.14 * c.Radius * c.Radius
}

func main() {
    var shape Shape
    circle := Circle{Radius: 5.0}
    shape = circle

    // 類型斷言
    if c, ok := shape.(Circle); ok {
        fmt.Printf("Type assertion successful. Radius: %.2f\n", c.Radius)
    } else {
        fmt.Println("Type assertion failed")
    }
}
  • 類型判斷
    類型判斷用于根據(jù)不同的類型執(zhí)行相應(yīng)的代碼塊。
func calculateArea(shape Shape) {
    switch v := shape.(type) {
    case Circle:
        fmt.Printf("Area of circle: %.2f\n", v.Area())
    default:
        fmt.Println("Unknown shape")
    }
}

func main() {
    circle := Circle{Radius: 5.0}
    calculateArea(circle)
}

3.5.6 接口組合

3.5.7 Any類型

由于Go中任何對象實例都滿足空接口interface{} 所以录择,interface{}看起來像是可以指向任何對象的Any類型拔莱。
當函數(shù)可以接受任意的對象實例時,我們會將其聲明為interface{}

func Printf(fmt string, args ...interface{})

四隘竭、并發(fā)編程


4.1 并發(fā)基礎(chǔ)

并發(fā)的幾種主流的實現(xiàn)模型:

  • 多進程
    開銷最大塘秦,好處在于簡單、進程間互不影響
  • 多線程
    比進程開銷小动看,但其開銷依舊較大
  • 基于回調(diào)的非阻塞/異步IO
    使用多線程模式會很快耗盡服務(wù)器的內(nèi)存和CPU資源尊剔。而這種模式通過事件驅(qū)動的方式使用異步IO,使服務(wù)器持續(xù)運轉(zhuǎn)弧圆,且盡可能地少用線程赋兵,降低開銷。但是編程復(fù)雜搔预。
  • 協(xié)程
    本質(zhì)上是一種用戶態(tài)線程霹期,不需要操作系統(tǒng)來進行搶占式調(diào)度,系統(tǒng)開銷極小拯田,可以有效提高線程的任務(wù)并發(fā)性历造。使用協(xié)程的優(yōu)點是編程簡單,結(jié)構(gòu)清晰船庇;缺點是需要語言支持吭产。

4.2 協(xié)程

Go語言在語言級別支持輕量級線程,叫g(shù)oroutine鸭轮。其讓輕量級線程的切換管理不依賴于系統(tǒng)的線程和進程臣淤,也不依賴于CPU的核心數(shù)量。

4.3 goroutine

goroutine是Go語言中輕量級線程實現(xiàn)窃爷,由Go運行時管理邑蒋。
加上go關(guān)鍵字姓蜂,這次調(diào)用就會在一個新的goroutine中并發(fā)執(zhí)行,當被調(diào)用的函數(shù)返回時医吊,這個gorontine也就結(jié)束了钱慢。如果這個函數(shù)由返回值,其返回值會被拋棄卿堂。

4.4 并發(fā)通信

Go語言以消息機制而非共享內(nèi)存作為通信方式
消息機制認為每個并發(fā)單元是自包含的束莫,獨立的個體,并且都有自己的變量草描,但在不同的并發(fā)單元間這些變量不共享览绿。每個并發(fā)單元的輸入和輸出只有一種,那就是消息陶珠。類似于進程的概念挟裂,每個進程不會被其他進程打擾。
這種消息機制被稱為Channel揍诽。不要通過共享內(nèi)存來通信诀蓉,而應(yīng)該通過通信來共享內(nèi)存。

4.5 Channel

channel 是Go語言在語言級別提供的goroutine間的通信方式暑脆。channel是進程內(nèi)的通信方式渠啤。如果需要跨進程通信,我們建議用分布式系統(tǒng)的方法來解決添吗,比如使用Socket或者HTTP等通信協(xié)議沥曹。
channel是類型相關(guān)的,一個channel只能傳遞一種類型的值碟联。

  • 基本語法
var chanName chan ElementType
var m map[string] chan bool  //聲明一個map妓美,其元素類型是bool的channel
# 聲明并初始化
ch := make(chan int)

ch<-value
value := <-ch

向channel中寫入數(shù)據(jù)會導(dǎo)致程序阻塞,直到有其他goroutine從這個channel中讀取數(shù)據(jù)鲤孵。如果channel之前沒有寫入數(shù)據(jù)壶栋,那么從channel中讀數(shù)據(jù)也會導(dǎo)致程序阻塞。

  • select
    每個case語句里必須是一個channel操作
select {
  case <-chan1:
      ... //如chan1成功讀到數(shù)據(jù)普监,則進行該case處理語句贵试,并直接忽略掉讀到的數(shù)據(jù)
  case chan2<- 1:
    ...  //如果成功向chan2寫入數(shù)據(jù),則進行該case語句
  default:
    ...  //上面都沒有成功凯正,進入default
}

在 Go 語言的 select 語句中毙玻,如果多個 case 同時滿足條件,Go 會隨機選擇一個 case 執(zhí)行廊散,這也稱為偽隨機選擇桑滩。這意味著無法確定哪個 case 會被優(yōu)先選擇,因此我們不能依賴于特定 case 的執(zhí)行順序允睹。

  • 緩沖機制
    即使沒有讀取方运准,寫入方也可以一直往channel里寫入往声,在緩沖區(qū)填完之前都不會阻塞。
    c := make (chan int, 1024)

  • 超時機制
    channel實現(xiàn)超時機制

time out := make(chan bool, 1)
go func(){
  time.sleep(1e9)  //1s
  timeout <- true
}()

select{
  case <-ch:
  ...
  case <-timeout:
  ...
}

  • channel的傳遞
    channel 本身在定義后也可以通過channel來傳遞
    可以利用這個特性來實現(xiàn)管道特性

  • 單向channel
    單向channel只能用于發(fā)送或者接受數(shù)據(jù)戳吝。只是對channel的一種使用限制。
    我們在將一個channel變量傳遞到一個函數(shù)時贯涎,可以通過將其指定為單向channel變量听哭,從而限制該函數(shù)中可以對channel的操作,比如只能往這個channle寫或讀塘雳。

# 聲明
var ch1 chan int
var ch2 chan<-float64    //單向的陆盘,只能寫float64數(shù)據(jù)
var ch3 <-chan int  //單向的,只能讀取int數(shù)據(jù)

#初始化
ch4 := make(chan int)
ch5 := <-chan int(ch4)
ch6 := chan<- int(ch4)

#用法
func Parse(ch <-chan int){
  for value := range ch{
    ...
  }
}
  • 關(guān)閉channel
    close(ch)
    判斷是否已經(jīng)被關(guān)閉:
    x,ok := <-ch
    只需要看第二個bool返回值即可败明,false表示已經(jīng)被關(guān)閉

4.6 多核并行化

可以通過設(shè)置環(huán)境變量GOAMAXPROCS的值來控制使用多少給CPU核心
或者runtime.GOMAXPROCS()
runtime.NumCOU()獲取核心數(shù)

4.7 讓出時間片

runtime.Gosched()主動讓出時間片給其他goroutine
實際上隘马,要想精細控制goroutine行為,須要深入了解runtime包提供的具體功能妻顶。

4.8 同步

  • 同步鎖
    sync包提供了兩種鎖類型:sync.Mutex 和sync.RWMutex酸员。
    當一個goroutine獲取Mutex后,其他goroutine只能等到該goroutine釋放Mutex讳嘱。
    RWMutex是經(jīng)典的單寫多讀模型幔嗦,在讀鎖占用的情況下會阻止寫,但不阻止讀沥潭。從RWMutex的實現(xiàn)看邀泉,其組合了Mutex。讀鎖調(diào)用RLock()钝鸽,寫鎖Lock()
    任何一個Lock() 或RLock均需要保證對應(yīng)有Unlock或RUnlock()汇恤。
var l sync.Mutex
func foo() {
  l.Lock()
  defer l.Unlock()
}
  • 全局唯一操作
    對于從全局角度只需要運行一次的代碼,比如全局初始化操作拔恰,Go提供了一個Once類型來保證全局的唯一性操作因谎。
var once sync.Once
once.Do(func)

五、網(wǎng)絡(luò)編程


5.1 Socket編程

Go語言使用協(xié)議建立連接仁连,只需要調(diào)用net.Dial()即可蓝角。
func Dial(net, addr string) (Conn, error)

conn, err := net.Dial("tcp","192.168.0.10:2100")
conn,err := net.Dial("udp", "192.168.0.12:975")
conn,err := net.Dial("ip4:icmp","www.baidu.com") //ICMP連接

在建立成功后就可以用conn的Write()寫數(shù)據(jù),Read()讀數(shù)據(jù)

5.2HTTP編程

5.3RPC編程

RPC 是一種通過網(wǎng)絡(luò)從遠程計算機上請求服務(wù)饭冬,而不需要了解底層網(wǎng)絡(luò)細節(jié)的應(yīng)用程序通信協(xié)議使鹅。采用CS模式。

  • Go中的RPC支持與處理
    在net/rpc中實現(xiàn)了RPC昌抠,其允許客戶端程序通過網(wǎng)絡(luò)或者其他IO連接調(diào)用一個遠端對象的公開方法患朱。

服務(wù)端:將對象注冊為可訪問的服務(wù),該對象的方法需滿足:
必須是公開的炊苫、必須兩個參數(shù)裁厅,且參數(shù)類型都必須是包外部可訪問的或者是內(nèi)置類型冰沙、第二個參數(shù)必須是一個指針、必須返回一個error類型的值执虹。
func (t *T) MethodName(argType T1, relpayType *T2) error
第一個參數(shù)表示客戶端傳入的參數(shù)拓挥,第二個參數(shù)表示要返回給客戶端的結(jié)果。

RPC服務(wù)端通過調(diào)用rpc.ServerConn處理單個連接請求袋励。

RPC客戶端侥啤,可用rpc.Dial() 或rpc.DialHTTP()方法來與指定的RPC服務(wù)端建立連接。建立連接后茬故,可以同步或異步的方式接受RPC服務(wù)端的處理結(jié)果盖灸。調(diào)用RPC客戶端的Call()方法則進行同步處理。調(diào)用客戶端的Go()方法時磺芭,可以進行異步處理赁炎。

//服務(wù)定義
package math

type MathService struct{}

func (m *MathService) Add(args *Args, reply *int) error {
    *reply = args.A + args.B
    return nil
}

type Args struct {
    A, B int
}
// 服務(wù)端
func main() {
    mathService := new(math.MathService)
    rpc.Register(mathService)

    listener, err := net.Listen("tcp", ":1234")
    if err != nil {
        log.Fatal("Error starting listener:", err)
    }

    defer listener.Close()
    fmt.Println("Server is listening on port 1234")

    for {
        conn, err := listener.Accept()
        if err != nil {
            log.Fatal("Error accepting connection:", err)
        }
        go rpc.ServeConn(conn)
    }
}
//客戶端
func main() {
    client, err := rpc.Dial("tcp", "localhost:1234")
    if err != nil {
        log.Fatal("Error connecting to server:", err)
    }

    args := &math.Args{A: 10, B: 5}

    var reply int

    err = client.Call("MathService.Add", args, &reply)
    if err != nil {
        log.Fatal("Error calling MathService.Add:", err)
    }
    fmt.Printf("Add result: %d + %d = %d\n", args.A, args.B, reply)
}

5.4 JSON處理

  • 編碼為JSON格式
    json.Marshal() 可對一組數(shù)據(jù)進行JSON編碼,將結(jié)構(gòu)體轉(zhuǎn)為json
    json.Unmarshal(jsonData, &結(jié)構(gòu)體對象) 將json轉(zhuǎn)為結(jié)構(gòu)體
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末钾腺,一起剝皮案震驚了整個濱河市徙垫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌放棒,老刑警劉巖松邪,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異哨查,居然都是意外死亡逗抑,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進店門寒亥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來邮府,“玉大人,你說我怎么就攤上這事溉奕」涌” “怎么了?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵加勤,是天一觀的道長仙辟。 經(jīng)常有香客問我,道長鳄梅,這世上最難降的妖魔是什么叠国? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮戴尸,結(jié)果婚禮上粟焊,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好项棠,可當我...
    茶點故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布悲雳。 她就那樣靜靜地躺著,像睡著了一般香追。 火紅的嫁衣襯著肌膚如雪合瓢。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天透典,我揣著相機與錄音歪玲,去河邊找鬼。 笑死掷匠,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的岖圈。 我是一名探鬼主播讹语,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蜂科!你這毒婦竟也來了顽决?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤导匣,失蹤者是張志新(化名)和其女友劉穎才菠,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體贡定,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡赋访,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了缓待。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蚓耽。...
    茶點故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖旋炒,靈堂內(nèi)的尸體忽然破棺而出步悠,到底是詐尸還是另有隱情,我是刑警寧澤瘫镇,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布鼎兽,位于F島的核電站,受9級特大地震影響铣除,放射性物質(zhì)發(fā)生泄漏谚咬。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一尚粘、第九天 我趴在偏房一處隱蔽的房頂上張望序宦。 院中可真熱鬧,春花似錦、人聲如沸互捌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽秕噪。三九已至钳降,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間腌巾,已是汗流浹背遂填。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留澈蝙,地道東北人吓坚。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像灯荧,于是被迫代替她去往敵國和親礁击。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,969評論 2 355

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