Golang Packages---fmt(1)

看了半個月的go基礎,對go語法有了大致的了解,發現go真的很強大,特別是golang標準庫中的包。在這里更新一下golang的常用包,也加深一下記憶。

fmt包

fmt包是最新學習golang引入的第一個包,也是最多的包 .
import "fmt"
mt包實現了類似C語言printf和scanf的格式化I/O。格式化verb('verb')源自C語言但更簡單。

Printing

verb:
通用:

%v  值的默認格式表示。當輸出結構體時,擴展標志(%+v)會添加字段名
%#v 值的Go語法表示
%T  值的類型的Go語法表示
%%  百分號

布爾值:

%t  單詞true或false

整數:

%b  表示為二進制
%c  該值對應的unicode碼值
%d  表示為十進制
%o  表示為八進制
%q  該值對應的單引號括起來的go語法字符字面值,必要時會采用安全的轉義表示
%x  表示為十六進制,使用a-f
%X  表示為十六進制,使用A-F
%U  表示為Unicode格式:U+1234,等價于"U+%04X"

浮點數、復數的兩個組分:

%b  無小數部分、二進制指數的科學計數法,如-123456p-78;參見strconv.FormatFloat %e 科學計數法,如-1234.456e+78 %E 科學計數法,如-1234.456E+78 %f 有小數部分但無指數部分,如123.456 %F 等價于%f %g    根據實際情況采用%e或%f格式(以獲得更簡潔、準確的輸出)
%G  根據實際情況采用%E或%F格式(以獲得更簡潔、準確的輸出)
字符串和[]byte:
%s  直接輸出字符串或者[]byte %q  該值對應的雙引號括起來的go語法字符串字面值,必要時會采用安全的轉義表示
%x  每個字節用兩字符十六進制數表示(使用a-f)
%X  每個字節用兩字符十六進制數表示(使用A-F)

指針:

%p  表示為十六進制,并加上前導的0x

沒有verb %u。整數如果是無符號類型自然輸出也是無符號的。類似的,也沒有必要指定操作數的尺寸(int8,int64)。

寬度通過一個緊跟在百分號后面的十進制數指定,如果未指定寬度,則表示值時除必需之外不作填充。精度通過(可能有的)寬度后跟點號后跟的十進制數指定。如果未指定精度,會使用默認精度;如果點號后沒有跟數字,表示精度為0。舉例如下:

%f:    默認寬度,默認精度
%9f    寬度9,默認精度
%.2f   默認寬度,精度2 %9.2f  寬度9,精度2 %9.f   寬度9,精度0

寬度和精度格式化控制的是Unicode碼值的數量(不同于C的printf,它的這兩個因數指的是字節的數量)。兩者任一個或兩個都可以使用''號取代,此時它們的值將被對應的參數(按''號和verb出現的順序,即控制其值的參數會出現在要表示的值前面)控制,這個操作數必須是int類型。

對于大多數類型的值,寬度是輸出的最小字符數,如果必要是會用空格填充。對于字符串,寬度是輸出字符數目的最低數量,如果必要會截斷字符串。

對于整數,寬度和精度都設置輸出總長度。采用精度時表示右對齊并用0填充,而寬度默認表示用空格填充。

對于浮點數,寬度設置輸出總長度;精度設置小數部分長度(如果有的話),除了%g/%G,此時精度設置總的數字個數。例如,對數字123.45,格式%6.2f 輸出123.45;格式%.4g輸出123.5。%e和%f的默認精度是6,%g的默認精度是可以將該值區分出來需要的最小數字個數。

對復數,寬度和精度會分別用于實部和虛部,結果用小括號包裹。因此%f用于1.2+3.4i輸出(1.200000+3.400000i)。

其它flag:

+   總是輸出數值的正負號;對%q(%+q)會生成全部是ASCII字符的輸出(通過轉義);
-   在輸出右邊填充空白而不是默認的左邊(即從默認的右對齊切換為左對齊);
# 切換格式:
  八進制數前加0(%#o),十六進制數前加0x(%#x)或
 0X(%#X),指針去掉前面的0x(%#p);
    對%q(%#q),如果strconv.CanBackquote返回真會輸出反引號括起來的未轉義字符串;
    對%U(%#U),如果字符是可打印的,會在輸出Unicode格式、空格、單引號括起來的go字面值;
' ' 對數值,正數前加空格而負數前加負號;
    對字符串采用%x或%X時(% x或% X)會給各打印的字節之間加空格;
0   使用0而不是空格填充,對于數值類型會把填充的0放在正負號后面;

erb會忽略不支持的flag。例如,因為沒有十進制切換模式,所以%#d和%d的輸出是相同的。

對每一個類似Printf的函數,都有對應的Print型函數,該函數不接受格式字符串,就效果上等價于對每一個參數都是用verb %v。另一個變體Println型函數會在各個操作數的輸出之間加空格并在最后換行。

不管verb如何,如果操作數是一個接口值,那么會使用接口內部保管的值,而不是接口,因此:

var i interface{} = 23
fmt.Printf("%v\n", i)

會輸出23。

除了verb %T和%p之外;對實現了特定接口的操作數會考慮采用特殊的格式化技巧。按應用優先級如下:

  1. 如果操作數實現了Formatter接口,會調用該接口的方法。Formatter提供了格式化的控制。

  2. 如果verb %v配合flag #使用(%#v),且操作數實現了GoStringer接口,會調用該接口。

如果操作數滿足如下兩條任一條,對于%s、%q、%v、%x、%X五個verb,將考慮:

  1. 如果操作數實現了error接口,Error方法會用來生成字符串,隨后將按給出的flag(如果有)和verb格式化。

  2. 如果操作數具有String方法,這個方法將被用來生成字符串,然后將按給出的flag(如果有)和verb格式化。

復合類型的操作數,如切片和結構體,格式化動verb遞歸地應用于其每一個成員,而不是作為整體一個操作數使用。因此%q會將[]string的每一個成員括起來,%6.2f會控制浮點數組的每一個元素的格式化。

為了避免可能出現的無窮遞歸,如:

type X string
func (x X) String() string { return Sprintf("<%s>", x) }

應在遞歸之前轉換值的類型:

func (x X) String() string { return Sprintf("<%s>", string(x)) }

顯式指定參數索引:

在Printf、Sprintf、Fprintf三個函數中,默認的行為是對每一個格式化verb依次對應調用時成功傳遞進來的參數。但是,緊跟在verb之前的[n]符號表示應格式化第n個參數(索引從1開始)。同樣的在'*'之前的[n]符號表示采用第n個參數的值作為寬度或精度。在處理完方括號表達式[n]后,除非另有指示,會接著處理參數n+1,n+2……(就是說移動了當前處理位置)。例如:

fmt.Sprintf("%[2]d %[1]d\n", 11, 22)

會生成"22 11",而:

fmt.Sprintf("%[3]*.[2]*[1]f", 12.0, 2, 6),

等價于:

fmt.Sprintf("%6.2f", 12.0),

會生成" 12.00"。因為顯式的索引會影響隨后的verb,這種符號可以通過重設索引用于多次打印同一個值:

fmt.Sprintf("%d %d %#[1]x %#x", 16, 17)

會生成"16 17 0x10 0x11"

格式化錯誤:

如果給某個verb提供了非法的參數,如給%d提供了一個字符串,生成的字符串會包含該問題的描述,如下所例:

錯誤的類型或未知的verb:%!verb(type=value)
    Printf("%d", hi):          %!d(string=hi)
太多參數(采用索引時會失效):%!(EXTRA type=value)
    Printf("hi", "guys"):      hi%!(EXTRA string=guys)
太少參數: %!verb(MISSING)
    Printf("hi%d"):            hi %!d(MISSING)
寬度/精度不是整數值:%!(BADWIDTH) or %!(BADPREC)
    Printf("%*s", 4.5, "hi"):  %!(BADWIDTH)hi
    Printf("%.*s", 4.5, "hi"): %!(BADPREC)hi
沒有索引指向的參數:%!(BADINDEX)
    Printf("%*[2]d", 7):       %!d(BADINDEX)
    Printf("%.[2]d", 7):       %!d(BADINDEX)

所有的錯誤都以字符串"%!"開始,有時會后跟單個字符(verb標識符),并以加小括弧的描述結束。

如果被print系列函數調用時,Error或String方法觸發了panic,fmt包會根據panic重建錯誤信息,用一個字符串說明該panic經過了fmt包。例如,一個String方法調用了panic("bad"),生成的格式化信息差不多是這樣的:

%!s(PANIC=bad)

%!s指示表示錯誤(panic)出現時的使用的verb。

Scanning
一系列類似的函數可以掃描格式化文本以生成值。

Scan、Scanf和Scanln從標準輸入os.Stdin讀取文本;Fscan、Fscanf、Fscanln從指定的io.Reader接口讀取文本;Sscan、Sscanf、Sscanln從一個參數字符串讀取文本。

Scanln、Fscanln、Sscanln會在讀取到換行時停止,并要求一次提供一行所有條目;Scanf、Fscanf、Sscanf只有在格式化文本末端有換行時會讀取到換行為止;其他函數會將換行視為空白。

Scanf、Fscanf、Sscanf會根據格式字符串解析參數,類似Printf。例如%x會讀取一個十六進制的整數,%v會按對應值的默認格式讀取。格式規則類似Printf,有如下區別:

%p 未實現
%T 未實現
%e %E %f %F %g %G 效果相同,用于讀取浮點數或復數類型
%s %v 用在字符串時會讀取空白分隔的一個片段
flag # 和 + 未實現

在無格式化verb或verb %v下掃描整數時會接受常用的進制設置前綴0(八進制)和0x(十六進制)。

寬度會在輸入文本中被使用(%5s表示最多讀取5個rune來生成一個字符串),但沒有使用精度的語法(沒有%5.2f,只有%5f)。

當使用格式字符串進行掃描時,多個連續的空白字符(除了換行符)在輸出和輸出中都被等價于一個空白符。在此前提下,格式字符串中的文本必須匹配輸入的文本;如果不匹配掃描會中止,函數的整數返回值說明已經掃描并填寫的參數個數。

在所有的掃描函數里,\r\n都被視為\n。

在所有的掃描函數里,如果一個操作數實現了Scan方法(或者說,它實現了Scanner接口),將會使用該接口為該操作數掃描文本。另外,如果如果掃描到(準備填寫)的參數比提供的參數個數少,會返回一個錯誤。

提供的所有參數必須為指針或者實現了Scanner接口。注意:Fscan等函數可能會在返回前多讀取一個rune,這導致多次調用這些函數時可能會跳過部分輸入。只有在輸入里各值之間沒有空白時,會出現問題。如果提供給Fscan等函數的io.Reader接口實現了ReadRune方法,將使用該方法讀取字符。如果該io.Reader接口還實現了UnreadRune方法,將是使用該方法保存字符,這樣可以使成功執行的Fscan等函數不會丟失數據。如果要給一個沒有這兩個方法的io.Reader接口提供這兩個方法,使用bufio.NewReader。

Index

  • type Stringer
  • type GoStringer
  • type State
  • type Formatter
  • type ScanState
  • type Scanner
  • func Printf(format string, a ...interface{}) (n int, err error)
  • func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error)
  • func Sprintf(format string, a ...interface{}) string
  • func Print(a ...interface{}) (n int, err error)
  • func Fprint(w io.Writer, a ...interface{}) (n int, err error)
  • func Sprint(a ...interface{}) string
  • func Println(a ...interface{}) (n int, err error)
  • func Fprintln(w io.Writer, a ...interface{}) (n int, err error)
  • func Sprintln(a ...interface{}) string
  • func Errorf(format string, a ...interface{}) error
  • func Scanf(format string, a ...interface{}) (n int, err error)
  • func Fscanf(r io.Reader, format string, a ...interface{}) (n int, err error)
  • func Sscanf(str string, format string, a ...interface{}) (n int, err error)
  • func Scan(a ...interface{}) (n int, err error)
  • func Fscan(r io.Reader, a ...interface{}) (n int, err error)
  • func Sscan(str string, a ...interface{}) (n int, err error)
  • func Scanln(a ...interface{}) (n int, err error)
  • func Fscanln(r io.Reader, a ...interface{}) (n int, err error)
  • func Sscanln(str string, a ...interface{}) (n int, err error)

type Stringer

type Stringer interface { String() [string]}

實現了Stringer接口的類型(即有String方法),定義了該類型值的原始顯示。當采用任何接受字符的verb(%v %s %q %x %X)動作格式化一個操作數時,或者被不使用格式字符串如Print函數打印操作數時,會調用String方法來生成輸出的文本。

type GoStringer

type GoStringer interface { GoString() [string] }

實現了GoStringer接口的類型(即有GoString方法),定義了該類型值的go語法表示。當采用verb %#v格式化一個操作數時,會調用GoString方法來生成輸出的文本。

type State

type State interface { // Write方法用來寫入格式化的文本 Write(b [][byte]) , err [error]) // Width返回寬度值,及其是否被設置 Width() (wid [int], ok [bool]) // Precision返回精度值,及其是否被設置 Precision() (prec [int], ok [bool]) // Flag報告是否設置了flag c(一個字符,如+、-、#等) Flag(c [int]) [bool] }

State代表一個傳遞給自定義Formatter接口的Format方法的打印環境。它實現了io.Writer接口用來寫入格式化的文本,還提供了該操作數的格式字符串指定的選項和寬度、精度信息(通過調用方法)。

type Formatter

type Formatter interface { // c為verb,f提供verb的細節信息和Write方法用于寫入生成的格式化文本 Format(f State, c [rune])
}

實現了Formatter接口的類型可以定制自己的格式化輸出。Format方法的實現內部可以調用Sprint或Fprint等函數來生成自身的輸出。

type ScanState

type ScanState interface { // 從輸入讀取下一個rune(Unicode碼值),在讀取超過指定寬度時會返回EOF // 如果在Scanln、Fscanln或Sscanln中被調用,本方法會在返回第一個'\n'后再次調用時返回EOF ReadRune() (r [rune] size [int](https://godoc.org/builtin#int), err [error]) // UnreadRune方法讓下一次調用ReadRune時返回上一次返回的rune且不移動讀取位置 UnreadRune() [error]// SkipSpace方法跳過輸入中的空白,換行被視為空白 // 在Scanln、Fscanln或Sscanln中被調用時,換行被視為EOF SkipSpace() // 方法從輸入中依次讀取rune并用f測試,直到f返回假;將讀取的rune組織為一個[]byte切片返回。 // 如果skipSpace參數為真,本方法會先跳過輸入中的空白。 // 如果f為nil,會使用!unicode.IsSpace(c);就是說返回值token將為一串非空字符。 // 換行被視為空白,在Scanln、Fscanln或Sscanln中被調用時,換行被視為EOF。 // 返回的切片指向一個共享內存,可能被下一次調用Token方法時重寫; // 或被使用該Scanstate的另一個Scan函數重寫;或者在本次調用的Scan方法返回時重寫。 Token(skipSpace [bool], f func([rune]) [bool]) (token [][byte], err [error]) // Width返回返回寬度值,及其是否被設置。單位是unicode碼值。 Width() (wid [int], ok [bool]) // 因為本接口實現了ReadRune方法,Read方法永遠不應被在Scanner接口中使用。 // 一個合法的ScanStat接口實現可能會選擇讓本方法總是返回錯誤。 Read(buf [][byte]) (n [int], err [error])
}

ScanState代表一個將傳遞給Scanner接口的Scan方法的掃描環境。 Scan函數中,可以進行一次一個rune的掃描,或者使用Token方法獲得下一個token(比如空白分隔的token)。

type Scanner

type Scanner interface { Scan(state ScanState, verb [rune]) [error]}

當Scan、Scanf、Scanln或類似函數接受實現了Scanner接口的類型(其Scan方法的receiver必須是指針,該方法從輸入讀取該類型值的字符串表示并將結果寫入receiver)的指針作為參數時,會調用其Scan方法進行定制的掃描。

func Printf

func Printf(format [string], a ...interface{}) (n [int], err [error])

Printf根據format參數生成格式化的字符串并寫入標準輸出。返回寫入的字節數和遇到的任何錯誤。

func Fprintf

func Fprintf(w [io].[Writer], format [string], a ...interface{}) (n [int], err [error])

Fprintf根據format參數生成格式化的字符串并寫入w。返回寫入的字節數和遇到的任何錯誤。

func Sprintf

func Sprintf(format [string], a ...interface{}) [string]

Sprintf根據format參數生成格式化的字符串并返回該字符串。

func Print

func Print(a ...interface{}) (n [int], err [error])

Print采用默認格式將其參數格式化并寫入標準輸出。如果兩個相鄰的參數都不是字符串,會在它們的輸出之間添加空格。返回寫入的字節數和遇到的任何錯誤。

func Fprint

func Fprint(w [io].[Writer], a ...interface{}) (n [int], err [error]

Fprint采用默認格式將其參數格式化并寫入w。如果兩個相鄰的參數都不是字符串,會在它們的輸出之間添加空格。返回寫入的字節數和遇到的任何錯誤。

func Sprint

func Sprint(a ...interface{}) [string]

Sprint采用默認格式將其參數格式化,串聯所有輸出生成并返回一個字符串。如果兩個相鄰的參數都不是字符串,會在它們的輸出之間添加空格。

func Println

func Println(a ...interface{}) (n [int], err [error]

Println采用默認格式將其參數格式化并寫入標準輸出。總是會在相鄰參數的輸出之間添加空格并在輸出結束后添加換行符。返回寫入的字節數和遇到的任何錯誤。

func Fprintln

func Fprintln(w [io].[Writer], a ...interface{}) (n [int], err [error])

Fprintln采用默認格式將其參數格式化并寫入w。總是會在相鄰參數的輸出之間添加空格并在輸出結束后添加換行符。返回寫入的字節數和遇到的任何錯誤。

func Sprintln

func Sprintln(a ...interface{}) [string]

Sprintln采用默認格式將其參數格式化,串聯所有輸出生成并返回一個字符串。總是會在相鄰參數的輸出之間添加空格并在輸出結束后添加換行符。

func Errorf

func Errorf(format [string], a ...interface{}) [error]

Errorf根據format參數生成格式化字符串并返回一個包含該字符串的錯誤。

func Scanf

func Scanf(format [string], a ...interface{}) (n [int], err [error])

Scanf從標準輸入掃描文本,根據format 參數指定的格式將成功讀取的空白分隔的值保存進成功傳遞給本函數的參數。返回成功掃描的條目個數和遇到的任何錯誤。

func Fscanf

func Fscanf(r [io](https://godoc.org/io).[Reader], format [string], a ...interface{}) (n [int] err [error])

Fscanf從r掃描文本,根據format 參數指定的格式將成功讀取的空白分隔的值保存進成功傳遞給本函數的參數。返回成功掃描的條目個數和遇到的任何錯誤。

func Sscanf

func Sscanf(str [string](https://godoc.org/builtin#string), format [string](https://godoc.org/builtin#string), a ...interface{}) (n [int](https://godoc.org/builtin#int), err [error](https://godoc.org/builtin#error))

Sscanf從字符串str掃描文本,根據format 參數指定的格式將成功讀取的空白分隔的值保存進成功傳遞給本函數的參數。返回成功掃描的條目個數和遇到的任何錯誤。

func Scan

func Scan(a ...interface{}) (n [int](https://godoc.org/builtin#int), err [error](https://godoc.org/builtin#error))

Scan從標準輸入掃描文本,將成功讀取的空白分隔的值保存進成功傳遞給本函數的參數。換行視為空白。返回成功掃描的條目個數和遇到的任何錯誤。如果讀取的條目比提供的參數少,會返回一個錯誤報告原因。

func Fscan

func Fscan(r [io](https://godoc.org/io).[Reader](https://godoc.org/io#Reader), a ...interface{}) (n [int](https://godoc.org/builtin#int), err [error](https://godoc.org/builtin#error))

Fscan從r掃描文本,將成功讀取的空白分隔的值保存進成功傳遞給本函數的參數。換行視為空白。返回成功掃描的條目個數和遇到的任何錯誤。如果讀取的條目比提供的參數少,會返回一個錯誤報告原因。

func Sscan

func Sscan(str [string](https://godoc.org/builtin#string), a ...interface{}) (n [int](https://godoc.org/builtin#int), err [error](https://godoc.org/builtin#error))

Sscan從字符串str掃描文本,將成功讀取的空白分隔的值保存進成功傳遞給本函數的參數。換行視為空白。返回成功掃描的條目個數和遇到的任何錯誤。如果讀取的條目比提供的參數少,會返回一個錯誤報告原因。

func Scanln

func Scanln(a ...interface{}) (n [int](https://godoc.org/builtin#int), err [error](https://godoc.org/builtin#error))

Scanln類似Scan,但會在換行時才停止掃描。最后一個條目后必須有換行或者到達結束位置。

func Fscanln

func Fscanln(r [io](https://godoc.org/io).[Reader](https://godoc.org/io#Reader), a ...interface{}) (n [int](https://godoc.org/builtin#int), err [error](https://godoc.org/builtin#error))

Fscanln類似Fscan,但會在換行時才停止掃描。最后一個條目后必須有換行或者到達結束位置。

func Sscanln

func Sscanln(str [string](https://godoc.org/builtin#string), a ...interface{}) (n [int](https://godoc.org/builtin#int), err [error](https://godoc.org/builtin#error))

Sscanln類似Sscan,但會在換行時才停止掃描。最后一個條目后必須有換行或者到達結束位置。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,578評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,701評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,691評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,974評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,694評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,026評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,015評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,193評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,719評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,442評論 3 360
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,668評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,151評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,846評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,255評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,592評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,394評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,635評論 2 380