Go教程第八篇:Array和Slice

Array和Slice

歡迎來到《Golang系列教程》的第八篇赁濒,在這篇教程中毛嫉,我們將處理Go中的Array和Slice。

Array

數(shù)組是同一類型的元素的集合汇跨,比如,5,8,9,79,76是一組整型妆距,他們就可以組成一個數(shù)組穷遂。在Go中不同類型的值不允許放入到同一個數(shù)組中。

數(shù)組聲明

數(shù)組聲明:

[n]T
n表明了數(shù)組元素的個數(shù)娱据,T表明的是元素的數(shù)據(jù)類型蚪黑。另外,元素個數(shù)n也是類型的一部分(這點我們會在稍后講解)中剩。Go提供了多種聲明數(shù)組的方式忌穿,我們來一個個看下。

package main

import (
    "fmt"
)


func main() {
    var a [3]int //int array with length 3
    fmt.Println(a)
}

var a[3]int 包含了一個含有3個整數(shù)的數(shù)組结啼。數(shù)組中的所有元素的值都會自動地被初始化該數(shù)組類型所對應(yīng)的零值zero value掠剑。在本例中,a是一個整型數(shù)組郊愧,因此a的所有元素都會被初始化為0值澡腾,0即int類型的零值。運行上面的程序糕珊,得到的輸出結(jié)果是: [0 0 0]

數(shù)組的角標(biāo)是從:0到length-1动分。我們可以給上述數(shù)組分配一些值:

package main
import (
   "fmt"
)

func main() {
   var a [3]int //int array with length 3
   a[0] = 12 // array index starts at 0
   a[1] = 78
   a[2] = 50
   fmt.Println(a)
}

上面的程序會輸出:[12 78 50]。

我們還可以以一種快捷的方式創(chuàng)建該數(shù)組:

package main
import (
    "fmt"
)
func main() {
    a := [3]int{12, 78, 50} // short hand declaration to create array
    fmt.Println(a)
}

程序的輸出還是:[12 78 50]红选。

在快捷方式中澜公,不是所有的元素都要指定一個值:

package main

import (
    "fmt"
)

func main() {
    a := [3]int{12}
    fmt.Println(a)
}

在上面程序的第八行 a:=[3]int{12},聲明了一個長度為3的數(shù)組,但是只提供了一個值12。剩下的2個元素并沒有賦值坟乾,
而是交由編譯器自動初始化為0迹辐。程序的輸出結(jié)果為:[12 0 0]。

你甚至可以在聲明時忽略數(shù)組的長度甚侣,使用...代替明吩。這時,編譯器會自動幫你判斷出長度殷费。

package main
import (
    "fmt"
)

func main() {
    a := [...]int{12, 78, 50} // ... makes the compiler determine the length
    fmt.Println(a)
}

數(shù)組長度的大小也是數(shù)組類型的一部分印荔。因此,[5]int 和[25]int 是倆個不同的數(shù)組類型详羡。
正是因為這仍律,數(shù)組的大小不能改變。不過实柠,你也不用擔(dān)心水泉,因為,slice會解決這個問題窒盐。

package main

func main() {
    a := [3]int{5, 78, 8}
    var b [5]int
    b = a //not possible since [3]int and [5]int are distinct types
}

程序的第6行草则,當(dāng)我們試圖把一個[3]int 類型的變量賦值給一個int[5]類型的變量時,就不會編譯通過蟹漓。此時畔师,編譯器會拋出一個錯誤: main.go:6: cannot use a (type [3]int) as type [5]int in assignment.

數(shù)組是值類型

Go里面的數(shù)組是值類型而非引用類型,這意味著牧牢,當(dāng)他們被賦值給一個新變量的時候看锉,會把原始的數(shù)組拷貝給新變量。如果對新變量做出修改塔鳍,不會影響到原來的數(shù)組伯铣。

package main

import "fmt"

func main() {
    a := [...]string{"USA", "China", "India", "Germany", "France"}
    b := a // a copy of a is assigned to b
    b[0] = "Singapore"
    fmt.Println("a is ", a)
    fmt.Println("b is ", b)
}

在上面程序的第七行,會把a拷貝給b轮纫。在第八行腔寡,又把數(shù)組b的第一個元素置為"Singapore"。這不會影響到數(shù)組a掌唾。
程序?qū)⑤敵觯?/p>

a is [USA China India Germany France]
b is [Singapore China India Germany France]

同樣地放前,當(dāng)把數(shù)組作為參數(shù)傳遞給函數(shù)時,他們實際傳遞的也是值糯彬,原來的數(shù)組不會受到影響凭语。

package main

import "fmt"

func changeLocal(num [5]int) {
    num[0] = 55
    fmt.Println("inside function ", num)

}
func main() {
    num := [...]int{5, 6, 7, 8, 8}
    fmt.Println("before passing to function ", num)
    changeLocal(num) //num is passed by value
    fmt.Println("after passing to function ", num)
}

在上面程序的第13行,數(shù)組num實際是以值的形式傳遞給函數(shù)changeLocal()撩扒,因此這不會因函數(shù)的調(diào)用而受到影響似扔。該程序會輸出:

before passing to function  [5 6 7 8 8]
inside function  [55 6 7 8 8]
after passing to function  [5 6 7 8 8]

數(shù)組長度

把數(shù)組作為參數(shù)傳遞給len函數(shù),即可獲得數(shù)組的長度。

package main

import "fmt"

func main() {
    a := [...]float64{67.7, 89.8, 21, 78}
    fmt.Println("length of a is",len(a))

}

上述程序的輸出結(jié)果是: length of a is 4

使用角標(biāo)遍歷數(shù)組

for循環(huán)可用于遍歷數(shù)組:

package main

import "fmt"

func main() {
    a := [...]float64{67.7, 89.8, 21, 78}
    for i := 0; i < len(a); i++ { //looping from 0 to the length of the array
        fmt.Printf("%d th element of a is %.2f\n", i, a[i])
    }
}

上面的程序使用for循環(huán)來遍歷這個數(shù)組炒辉,角標(biāo)從0到length-1豪墅。程序?qū)敵鋈缦拢?/p>

0 th element of a is 67.70
1 th element of a is 89.80
2 th element of a is 21.00
3 th element of a is 78.00

Go提供了一個更好更簡潔的方式迭代數(shù)組,那就是使用range黔寇。range會把角標(biāo)和元素都返回來偶器。我們來用range重寫上面的代碼,計算出所有元素之和:

package main

import "fmt"

func main() {
    a := [...]float64{67.7, 89.8, 21, 78}
    sum := float64(0)
    for i, v := range a {//range returns both the index and value
        fmt.Printf("%d the element of a is %.2f\n", i, v)
        sum += v
    }
    fmt.Println("\nsum of all elements of a",sum)
}

在第八行缝裤,for i,v:=range a 就是使用range方式來遍歷數(shù)組a屏轰。range會返回index和value。
我們把值打印出來倘是,并計算數(shù)組a中的元素的和亭枷。程序的輸出如下:

0 the element of a is 67.70
1 the element of a is 89.80
2 the element of a is 21.00
3 the element of a is 78.00

sum of all elements of a 256.5

如果在某些情況下袭艺,你不想要index的話搀崭,你可以用"——"來代替:

for _, v := range a { //ignores index
}

上面的遍歷會忽略index。類似地猾编,value像這樣忽略瘤睹。

多維數(shù)組

我們上面創(chuàng)建的都是一些一維數(shù)組。創(chuàng)建多維數(shù)組的話答倡,可以這樣:

package main

import (
    "fmt"
)

func printarray(a [3][2]string) {
    for _, v1 := range a {
        for _, v2 := range v1 {
            fmt.Printf("%s ", v2)
        }
        fmt.Printf("\n")
    }
}

func main() {
    a := [3][2]string{
        {"lion", "tiger"},
        {"cat", "dog"},
        {"pigeon", "peacock"}, //this comma is necessary. The compiler will complain if you omit this comma
    }
    printarray(a)
    var b [3][2]string
    b[0][0] = "apple"
    b[0][1] = "samsung"
    b[1][0] = "microsoft"
    b[1][1] = "google"
    b[2][0] = "AT&T"
    b[2][1] = "T-Mobile"
    fmt.Printf("\n")
    printarray(b)
}

在上述程序的第17行轰传,我們聲明了一個2維的字符串?dāng)?shù)組。第二行中的,號是必須的瘪撇。因為語法分析器获茬,會自動地根據(jù)簡單的規(guī)則插入分號。如果你有興趣了解更多的話倔既,可以閱讀:semicolon恕曲。

在第23行,又聲明了第二個2維數(shù)組b渤涌,這個數(shù)組的元素是根據(jù)索引一個個添加的佩谣。這也是一種初始化二維數(shù)組的方法。

第7行的主函數(shù)使用倆個range來遍歷实蓬,從而打印出2維數(shù)組的內(nèi)容茸俭。程序會輸出如下:

lion tiger
cat dog
pigeon peacock

apple samsung
microsoft google
AT&T T-Mobile

以上這些就是關(guān)于數(shù)組的知識,數(shù)組雖然看起來很靈活安皱,但他們的限制就是他們都是固定長度调鬓。你沒辦法改變數(shù)組的長度。這時酌伊,slice就進(jìn)入到了我們的視野了袖迎。事實上,對Go來說,slice比傳統(tǒng)的數(shù)組更通用。

Slice

slice是在數(shù)組基礎(chǔ)上構(gòu)建出來的一個方便的燕锥、靈活的辜贵、強大的包裝類。slice本身不存儲任何數(shù)據(jù)归形,他們僅僅是對已有數(shù)組的引用托慨。

創(chuàng)建一個分片

語法:

[]T

T是slice的元素類型。

package main

import (
    "fmt"
)

func main() {
    a := [5]int{76, 77, 78, 79, 80}
    var b []int = a[1:4] //creates a slice from a[1] to a[3]
    fmt.Println(b)
}

a[start:end]這個語法暇榴,會從數(shù)組a的角標(biāo)start到end-1里創(chuàng)建一個slice厚棵。因此,在上述程序
的第9行a[1,4]會創(chuàng)建一個代表數(shù)組a的第1個元素到第3個元素的slice蔼紧。因此婆硬,slice b 的值為:
[77,78,79]。

我們再看一種創(chuàng)建slice的方式:

package main

import (
    "fmt"
)

func main() {
    c := []int{6, 7, 8} //creates and array and returns a slice reference
    fmt.Println(c)
}

上面這個程序的第九行奸例,c:=[]int{6,7,8}會創(chuàng)建一個含有3個元素的數(shù)組彬犯,同時返回一個slice引用
并把其賦值給變量c。

修改slice

slice自己并不存儲數(shù)據(jù)查吊。它僅僅是底層數(shù)組的一個表示谐区。對slice的任何修改都會影響到底層的數(shù)組。

package main

import (
    "fmt"
)

func main() {
    darr := [...]int{57, 89, 90, 82, 100, 78, 67, 69, 59}
    dslice := darr[2:5]
    fmt.Println("array before",darr)
    for i := range dslice {
        dslice[i]++
    }
    fmt.Println("array after",darr)
}

上述程序的第9行逻卖,我們從數(shù)組darr的腳標(biāo)2,3,4里創(chuàng)建了一個的dslice宋列。for循環(huán)會把腳標(biāo)內(nèi)的值加一。在for循環(huán)之后评也,我們把數(shù)組打印出來炼杖,程序的輸出結(jié)果,就如下展示:

array before [57 89 90 82 100 78 67 69 59]
array after [57 89 91 83 101 78 67 69 59]

當(dāng)有多個slice共享一個底層數(shù)組時盗迟,每一個slice做出的改變都將影響到底層的數(shù)組坤邪。

package main

import (
    "fmt"
)

func main() {
    numa := [3]int{78, 79 ,80}
    nums1 := numa[:] //creates a slice which contains all elements of the array
    nums2 := numa[:]
    fmt.Println("array before change 1",numa)
    nums1[0] = 100
    fmt.Println("array after modification to slice nums1", numa)
    nums2[1] = 101
    fmt.Println("array after modification to slice nums2", numa)
}

在第9行,numa[:]由于沒有指定起始腳標(biāo)和終止腳標(biāo)诈乒,它默認(rèn)會認(rèn)起始腳標(biāo)為0罩扇,終止腳標(biāo)為len(numa)。nums1和nums2由于共享同一個數(shù)組怕磨,所以程序的輸出如下:

array before change 1 [78 79 80]
array after modification to slice nums1 [100 79 80]
array after modification to slice nums2 [100 101 80]

從輸出結(jié)果可以看出喂饥,當(dāng)多個slice共享同一個底層數(shù)組時,每一個slice的改變都將影響到
底層數(shù)組肠鲫。

slice的長度和容量

slice的長度是其中的元素個數(shù)员帮。slice的容量為其底層數(shù)組從slice的開始腳標(biāo)開始一直到數(shù)組最后一個腳本為止的所有元素個數(shù)。

我們一起寫段代碼理解:

package main

import (
    "fmt"
)

func main() {
    fruitarray := [...]string{"apple", "orange", "grape", "mango", "water melon", "pine apple", "chikoo"}
    fruitslice := fruitarray[1:3]
    fmt.Printf("length of slice %d capacity %d", len(fruitslice), cap(fruitslice)) //length of fruitslice is 2 and capacity is 6
}

在上面的程序中导饲,fruitslice是從數(shù)組fruitarray的腳標(biāo)1到腳本2開始創(chuàng)建捞高。因此氯材,fruitslice的長度是2。

fruitarray的長度是7硝岗。因為fruitslice是從腳標(biāo)1開始處創(chuàng)建氢哮,所以fruitslice的容量即是從fruitarray中除去第一個元素之外的所有,本例中型檀,即是: 從"orange"開始冗尤,一直到"chikoo"。所以fruitslice的容量為:6胀溺。

在對slice再次切分時一定要切到它的容量處裂七,。除此之外的任何情況都會拋出一個運行期錯誤:

package main

import (
    "fmt"
)

func main() {
    fruitarray := [...]string{"apple", "orange", "grape", "mango", "water melon", "pine apple", "chikoo"}
    fruitslice := fruitarray[1:3]
    fmt.Printf("length of slice %d capacity %d\n", len(fruitslice), cap(fruitslice)) //length of is 2 and capacity is 6
    fruitslice = fruitslice[:cap(fruitslice)] //re-slicing furitslice till its capacity
    fmt.Println("After re-slicing length is",len(fruitslice), "and capacity is",cap(fruitslice))
}

在上述程序的第11行仓坞,fruitslice被再次切分至它的容量背零。上述程序會輸出:

length of slice 2 capacity 6
After re-slicing length is 6 and capacity is 6

使用make創(chuàng)建slice

func make([]T,len,cap) 可以用來創(chuàng)建slice,接收三個參數(shù): type, length,capacity无埃。
capacity參數(shù)是可選的徙瓶,如果不傳的話,默認(rèn)值為數(shù)組長度录语。make函數(shù)會創(chuàng)建一個array倍啥,并返回
一個指向它的slice禾乘。

package main

import (
    "fmt"
)

func main() {
    i := make([]int, 5, 5)
    fmt.Println(i)
}

使用make創(chuàng)建的slice澎埠,元素的默認(rèn)值為0。上述的程序會輸出結(jié)果如下:[0 0 0 0 0].

向slice中添加內(nèi)容

我們都知道數(shù)組的長度都是固定的始藕,不能增加蒲稳。而slice是動態(tài)的,新元素可以使用append函數(shù)被追加到slice中伍派。
append的函數(shù)定義是:func append(s []T, x ...T) []T江耀。

X...T表示的是: 該函數(shù)可以接收多個參數(shù)X。這種類型的函數(shù)被稱為:可變函數(shù)诉植。

你可以在心里會有這樣一個疑問祥国,既然slice的內(nèi)部機制是由底層的數(shù)組所支持的,而數(shù)組的長度是固定的晾腔。
那么為何slice的長度是可變的呢舌稀? 其實底層是這樣的,當(dāng)一個元素被追加到slice中時灼擂,是再次創(chuàng)建一個新
數(shù)組壁查,原有數(shù)組里面的元素被會copy到新數(shù)組中,同時返回一個指向新數(shù)組的slice剔应。此時睡腿,新slice的容量
為老slice容量的二倍语御,是不是很神奇?下面的程序?qū)湍憧辞暹@一點:

package main

import (
    "fmt"
)

func main() {
    cars := []string{"Ferrari", "Honda", "Ford"}
    fmt.Println("cars:", cars, "has old length", len(cars), "and capacity", cap(cars)) //capacity of cars is 3
    cars = append(cars, "Toyota")
    fmt.Println("cars:", cars, "has new length", len(cars), "and capacity", cap(cars)) //capacity of cars is doubled to 6
}

上面程序中席怪,cars的初始容量是3应闯。我們追加了一個元素到cars中去之后,此時cars的容量編程了原來的二倍挂捻,變成了6.
程序輸出如下:


cars: [Ferrari Honda Ford] has old length 3 and capacity 3
cars: [Ferrari Honda Ford Toyota] has new length 4 and capacity 6

slice 類型的零值是nil孽锥。值為nil的slice其長度和容量都是0。我們可以向值為nil的slice中追加元素:

package main

import (
    "fmt"
)

func main() {
    var names []string //zero value of a slice is nil
    if names == nil {
        fmt.Println("slice is nil going to append")
        names = append(names, "John", "Sebastian", "Vinay")
        fmt.Println("names contents:",names)
    }
}

在上面的程序中name的值nil细层。我們向其中追加了3個元素逊脯,程序?qū)⑤敵鋈缦拢?/p>

slice is nil going to append
names contents: [John Sebastian Vinay]

使用...運算符可以把一個slice追加到另一個slice中:

func main() {
    veggies := []string{"potatoes","tomatoes","brinjal"}
    fruits := []string{"oranges","apples"}
    food := append(veggies, fruits...)
    fmt.Println("food:",food)
}

上面程序的第10行,我們把fruits追加到veggies并返回一個food业踏。上述程序的輸出如下:
food: [potatoes tomatoes brinjal oranges apples]

slice作為參數(shù)傳遞

你可以認(rèn)為slice代表的是一個結(jié)構(gòu)類:

type slice struct {
    Length        int
    Capacity      int
    ZerothElement *byte
}

slice含有三個部分: 長度檬姥、容量、指向零值元素的數(shù)組捧搞。當(dāng)把一個slice傳遞給函數(shù)之后抵卫,雖然它是值傳遞,但是指針變量將指向同一個底層數(shù)組胎撇。因此當(dāng)slice作為參數(shù)傳遞給函數(shù)之后介粘,在函數(shù)內(nèi)部對此slice做出的修改,在此函數(shù)的外部也是可見的晚树。我們可以寫個程序檢查一下:

package main

import (
    "fmt"
)

func subtactOne(numbers []int) {
    for i := range numbers {
        numbers[i] -= 2
    }

}
func main() {
    nos := []int{8, 7, 6}
    fmt.Println("slice before function call", nos)
    subtactOne(nos)                               //function modifies the slice
    fmt.Println("slice after function call", nos) //modifications are visible outside
}

在17行的函數(shù)調(diào)用姻采,會把slice里面的每個元素減2。函數(shù)調(diào)用完成之后爵憎,再次打印slice慨亲,你可以清楚地看到這些變化。如果你把一個數(shù)組傳遞函數(shù)宝鼓,然后在函數(shù)內(nèi)部對此數(shù)組進(jìn)行的修改刑棵,在該函數(shù)外部則不可見。

slice before function call [8 7 6]
slice after function call [6 5 4]

多維slice

類似于數(shù)組愚铡,slice也可以有多維蛉签。

package main

import (
    "fmt"
)


func main() {
     pls := [][]string {
            {"C", "C++"},
            {"JavaScript"},
            {"Go", "Rust"},
            }
    for _, v1 := range pls {
        for _, v2 := range v1 {
            fmt.Printf("%s ", v2)
        }
        fmt.Printf("\n")
    }
}

程序的輸出如下:


C C++
JavaScript
Go Rust

內(nèi)存優(yōu)化

由于slice持有了一個指向底層數(shù)組的引用。所以沥寥,只要slice在內(nèi)存中碍舍,數(shù)組就不能給垃圾回收。現(xiàn)在假定我們有個非常大的數(shù)組营曼,而我們只關(guān)注于處理其中的一小部分乒验。之后,我們從此數(shù)組里面創(chuàng)建一個slice蒂阱,然后處理該slice锻全。有點至關(guān)重要狂塘,只要slice還在引用它,它就得一直存在于內(nèi)存中鳄厌。

解決這個問題的方法就是使用copy函數(shù) func copy(dst,scr []T) int 荞胡。這樣的話,我們就可以使用新的slice了嚎,而原始的數(shù)組就可以被垃圾回收了泪漂。

package main

import (
    "fmt"
)

func countries() []string {
    countries := []string{"USA", "Singapore", "Germany", "India", "Australia"}
    neededCountries := countries[:len(countries)-2]
    countriesCpy := make([]string, len(neededCountries))
    copy(countriesCpy, neededCountries) //copies neededCountries to countriesCpy
    return countriesCpy
}
func main() {
    countriesNeeded := countries()
    fmt.Println(countriesNeeded)
}

在上述程序的第9行,neededCountries :=countries[:len(countries)-2]從countries中創(chuàng)建出一個slice歪泳。程序的第11行萝勤,把neededCountries拷貝到countriesCpy中,并且在函數(shù)的最后一行把其返回∧派。現(xiàn)在countries數(shù)組就可以被垃圾回收了敌卓,因為neededCountries不再被引用了。

到目前為止 我已經(jīng)在單個程序中匯總了所有的概念伶氢,你可以從github上下載到趟径。github。以上就是關(guān)于array和slice的全部內(nèi)容癣防,感謝閱讀蜗巧,請留下您珍貴的反饋和評論。

致謝

感謝您閱讀本文蕾盯。如果有任何反饋和問題幕屹,請您在評論區(qū)留言。

備注

本文系翻譯之作原文博客地址

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末刑枝,一起剝皮案震驚了整個濱河市香嗓,隨后出現(xiàn)的幾起案子迅腔,更是在濱河造成了極大的恐慌装畅,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件沧烈,死亡現(xiàn)場離奇詭異掠兄,居然都是意外死亡,警方通過查閱死者的電腦和手機锌雀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進(jìn)店門蚂夕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人腋逆,你說我怎么就攤上這事婿牍。” “怎么了惩歉?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵等脂,是天一觀的道長俏蛮。 經(jīng)常有香客問我,道長上遥,這世上最難降的妖魔是什么搏屑? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮粉楚,結(jié)果婚禮上辣恋,老公的妹妹穿的比我還像新娘。我一直安慰自己模软,他們只是感情好伟骨,可當(dāng)我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著燃异,像睡著了一般底靠。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上特铝,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天暑中,我揣著相機與錄音,去河邊找鬼鲫剿。 笑死鳄逾,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的灵莲。 我是一名探鬼主播雕凹,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼政冻!你這毒婦竟也來了枚抵?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤明场,失蹤者是張志新(化名)和其女友劉穎汽摹,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體苦锨,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡逼泣,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了舟舒。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拉庶。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖秃励,靈堂內(nèi)的尸體忽然破棺而出氏仗,到底是詐尸還是另有隱情,我是刑警寧澤夺鲜,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布皆尔,位于F島的核電站帚稠,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏床佳。R本人自食惡果不足惜滋早,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望砌们。 院中可真熱鬧杆麸,春花似錦、人聲如沸浪感。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽影兽。三九已至揭斧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間峻堰,已是汗流浹背讹开。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留捐名,地道東北人旦万。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像镶蹋,于是被迫代替她去往敵國和親成艘。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,060評論 2 355

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