go語言io reader_Go語言學習入門篇用Go解決現代程式設計難題
技術標籤:go語言io reader
Go語言開發團隊花了很長時間來解決當今軟體開發人員面對的問題。開發人員在為專案選擇語言時,不得不在快速開發和效能之間做出選擇。C和C++這類語言提供了很快的執行速度,而Ruby和Python這類的語言則擅長快速開發。Go語言在這兩者之間架起了橋樑,不僅提供了高效能的語言,同時也讓開發更快速。作為一門語言,Go不僅定義了能做什麼,還定義了不能做什麼。Go語言簡潔到只有幾個關鍵字。Go語言的編譯器非常快,所以,Go開發者能顯著減少專案構建時間。另外Go語言內建併發機制,所以不用使用特定的執行緒庫。Go語言簡單且高效。Go語言還自帶垃圾回收器,不需要使用者管理記憶體。關鍵特性如下:
1、開發速度
Go語言使用了更加智慧的編譯器,並簡化了解決依賴的演算法,最終提供了趕快的編譯速度。在現代硬體上,編譯整個Go語言的原始碼樹只需要20秒。 2、併發Go語言對併發的支援是這門語言最重要的特性之一。goroutine很像執行緒,但是它的開銷遠小於執行緒,使用它需要的程式碼更少。通道(channel)是內建的資料結構,可以讓使用者在不同的goroutine之間同步傳送具有型別的訊息。這個特性細節如下:2.1、goroutine
Go語言中會使用同一個執行緒來執行多個goroutine,使用net/http庫直接使用了內建的goroutine。如果使用C或者Java,不得不寫大量的額外程式碼來使用執行緒。func log( msg string){//這裡是記錄一些日誌的程式碼}//其他程式碼裡發生錯誤,呼叫日誌函式golog("發生了錯誤")
2.2、通道
通道是一種資料結構,可以通過goroutine之間進行安全的資料通訊。通道可以幫助使用者避免在其他語言裡常見的共享記憶體的問題。在其他語言中,如果使用全域性變數或者共享記憶體,必須使用複雜的鎖機制來防止對同一個變數的不同步修改。為了解決這個問題,通道提供了一種新的模式,從而保證併發修改時的資料安全。通道這個模式保證同一時刻只會有一個goroutine修改資料。通道用於在幾個執行的goroutine中間傳送資料。 3、Go語言的資料型別Go語言提供了靈活的、無繼承的型別系統,無需降低效能就能最大程度上覆用程式碼。這個系統依然支援面向物件開發,而且避免了傳統面向物件的效能問題。Go語言使用組合(Composition)設計模式,只需要將一個型別嵌入到另外一個型別,就能複用所有的功能。另外Go語言還具有獨特的介面實現機制。
type User struct { id int name string email string}//宣告結構體型別變數並初始化零值(結構體中的每個欄位都會用零值初始化)var u1 User//賦值u1.id = 1u1.name = "zhangsan1"u1.email="[email protected]"
還可以用如下方式在變數宣告時進行初始化賦值:
//這種形式對宣告順序沒有要求u2 := User{ id:2, name:"zhangsan2", email:"[email protected]",}//這種形式要和結構體宣告中的欄位順序一致u3 := User{id:3, name:"zhangsan3", email:"[email protected]"}
基於已有型別
另一種宣告使用者自定義型別的方法是基於一個已有的型別,使用這種宣告型別的方法,從內建型別中創建出更多型別,賦予更高階的功能。
type Interger int
Go認為這兩種型別是不同的型別,不同型別不能相互賦值,也不會對不同型別的值做隱式轉換。3.2、Go介面
在Go語言中,的介面有下面幾
個特點:
可以包含0個或多個方法
只定義方法宣告,不包含實現
實現介面不需要顯式的宣告,只需實現相應方法即可
介面定義
type Namer interface { method1(param_list) return_list method2(param_list) return_list ...}
這裡的 Namer 就是介面的名字,只要符合識別符號的規則即可。不過,通常約定的介面的名字最好以 er, r, able 結尾(視情況而定),這樣一眼就知道它是介面。
介面實現
在 Go語言 中實現介面很簡單,不需要顯式的宣告實現了某個介面,想要實現某個介面,只需要實現介面中的所有方法即可。
package mainimport "fmt"import "math"type Shaper interface { Area() float32 Circumference() float32}type Rect struct { Width float32 Height float32}type Circle struct { Radius float32}func (r Rect) Area() int { return r.Width * r.Height}func (r Rect) Circumference() int { return 2 * (r.Width + r.Height)}func (c Circle) Area() int { return math.Pi * c.Radius * c.Radius}func (c Circle) Circumference() int { return math.Pi * 2 * c.Radius}func main() { r := Rect{10, 20} fmt.Printf("Rect w: %f, d: %f, Area: %f, Circumference: %f", r.Width, r.Height, r.Area(), r.Circumference()) c := Circle{5} fmt.Printf("Circle r: %f, Area: %f, Circumference: %f", c.Radius, c.Area(), c.Circumference()) }
上面我們定義了一個 Shaper 的介面,其中包含兩個方法 Area 和 Circumference,分別用來計算面積和周長。然後我們定義了兩個結構體 Rect, Circle 並分別實現了這兩個方法。但是上面的程式似乎並沒有體現出介面和兩個實現型別的關係,下面我們將他們關聯起來使用:
func showInfo(s Shaper) { fmt.Printf("Area: %f, Circumference: %f", s.Area(), s.Circumference())}
注意,這裡方法的引數是一個介面型別的,因此我們可以將實現介面的型別的例項傳遞進去,像下面這樣:
r := Rect{10, 20}showInfo(r)c := Circle{5}showInfo(c)
獲取實現介面的實際型別
在上面的 showInfo 中我們傳入了介面型別的物件,如果將實現了介面的型別傳遞進去,那麼會將實際型別的其他特性掩蓋住,因此通常我們會想要獲取其真正的型別, 可以使用下面的方法:
func showInfo(s Shaper) { switch s.(type) { case Rect: fmt.Println("This is Rect") case Circle: fmt.Println("This is Circle") } fmt.Printf("Area: %f, Circumference: %f\n", s.Area(), s.Circumference())}
標準庫中的常用介面
io.Reader 和 io.Writer
這兩個介面定義了實現io功能的基本操作,因此某種型別只要實現了這兩個介面就可以進行io操作。
例如,Reader 介面的定義為:
type Reader interface { Read(p []byte) (n int, err error)}
類似的實現了 Reader 介面的物件有: os.Stdout, os.Stderr, os.File 等等。可以使用 Read方法向其中寫入資料。
4、記憶體管理Go語言的垃圾回收會有一些額外的開銷,但是程式設計時,能顯著降低開發難度。Go語言把無趣的記憶體管理交給專業的編譯器去做,而讓程式設計師專注於業務開發。
5、Go版本HelloWorld讓我們看看用Go語言如何編寫經典的HelloWorld!
packagemain//Go語言組織成包 import"fmt"//引入外部庫funcmain(){//main函式是程式執行入口fmt.Println("HelloWorld!")}
6、小結
Go語言是現代的、快速的、帶有強大的標準庫
Go語言內建對併發的支援
Go語言使用介面作為程式碼複用的基礎模組